C++的I/O流体系
继承关系:
ios <-- istream/ostream
|--> istream <-- istrstream/ifstream/iostream
|--> ostream <-- ostrstream/ofstream/iostream
|--> iostream <-- strstream/fstream
istream及其子类支持输入操作
ostream及其子类支持输出操作
由istream和ostream共同派生的子类iostream既支持输入也支持输出。
1.通过ofstream类单参(文件路径)构造函数可以打开一个文件用于向文件中输出,如果文件不存在,该类的构造函数将以缺省的方式创建文件;
如果文件存在,进行覆盖
2.ofstream的两参数(文件路径,打开模式openmode)版本
ios::in:打开文件用于从文件中读取
ios::out:打开文件用于向文件中写入
ios::app:打开文件用于向文件中追加
ios::ate:打开文件,把文件位置设置到文件尾部,用于从文件读取
// 在打开文件流时使用ios::ate选项,将文件的get位置置于文件尾
ifstream ifs ("文件路径", ios::binary | ios::ate);
if (! ifs)
PrintError (__FILE__, __LINE__, "Cannot open input file");
size_t uBytes = ifs.tellg (); // 通过tellg()函数获取当前的get位置, 以此计算出文件的总字节数
char* pcBuffer = new char[uBytes]; // 有了总字节数,我们就可以分配足 够的内存,一次性地读取文件的全部内容
ifs.seekg (ios::beg); // 在读取之前一定要将文件的 get位置重置于文件起始处
ifs.read (pcBuffer, uBytes);//读取文件内容
ios::trunc: 打开文件的同时删除其原有内容,用于向文件中输入
ios::binary:以二进制模式打开文件,用于输入/输出
ofstream ofs ("xxx", ios::out|ios::trunc|ios::binary);
if (! ofs)
3.ifstream和ofstream用法基本相同,用于从文件中读取
但是ifstream要求指定的文件必须存在
4.输入流的提取操作>>在格式化提取的过程中,以空格、制表符、换行分隔
5.fstream以读和写(默认)的方式打开一个文件时,文件必须存在
6.tellg/tellp:获取当前文件位置(包括\n等)的下一个
p表示put、g表示get
tellp在将get位置调整到文件开始的同时,也改变了put位置
seekg/seekp:设置当前文件的get/set位置
1.单参: seekg(0)与seekg(ios::beg)完成相同的任务
2.双参:
第一个参数代表相对于第二个参数所指定位置的偏移量:
ios::beg:文件头如:fs.seekg (5, ios::beg);//从文件头(开始下标为0)开始数5个字符
如:1234 56.78 apples;//即5数字开始操作
ios::end:文件尾
ios::cur:当前位置如:fs.seekg (-6, ios::cur);
在上面的情况下:tellp/tellg都获取值为:0
如果文件位置被移到了文件的起始位置之前或结束位置之后,那么该文件流将进入一种错误状态。
这时程序对这个流所做的更进一步处理将会被暂停,直到我们通过clear() 函数清除了这种错误状态为止。
如:
#include <iostream>
#include <fstream>
using namespace std;
int main (int argc, char* argv[]) {
ofstream ofs1 ("ex01.txt");
if (! ofs1)
cerr << "Cannot open output file" << endl;
ofs1 << 1234 << " " << 56.78 << " " << "apples" << '\n';
ofs1.close ();
ofstream ofs2 ("ex01.txt", ios::app);
if (! ofs2)
cerr << "Cannot open output file" << endl;
ofs2 << "append_a_line\n";
ofs2.close ();
ifstream ifs1 ("ex01.txt");
if (! ifs1)
cerr << "Cannot open input file" << endl;
int n;
double f;
string str1, str2;
ifs1 >> n >> f >> str1 >> str2;
ifs1.close ();
cout << n << " " << f << " " << str1 << " " << str2 << endl;
////////////////////////////////////////////////////////////
fstream fs ("ex02.txt", ios::in | ios::out);
if (! fs)
cerr << "Cannot open file" << endl;
fs << 1234 << " " << 56.78 << " " << "apples" << '\n';
cout << fs.tellg () << endl;//获取当前文件位置
cout << fs.tellp () << endl;//获取当前文件位置
fs.seekg (5, ios::beg);//同seekp,都是设置当前文件位置
fs << 1;
fs.seekg (-6, ios::cur);
cout << fs.tellg () << endl;
cout << fs.tellp () << endl;
int n;
double f;
string str;
fs >> n >> f >> str;
fs.close ();
cout << n << " " << f << " " << str << endl;
return 0;
}
7.io的非格式化:
(1).ofs.put(char);//一次写入一个字符
(char = ifs.get()) != EOF//一次获取一个字符,不为文件结尾
(2).get()的三参数:定界符并不被提取,但文件位置会停在定界符处,下次读取会发生错误
char sz[4];
while (ifs.get (sz, sizeof (sz), '\n'))//自定义'\n'为定界符
{
cout << sz;
cout.flush ();//刷新输入输出才可能显示出来(字符少的时候)
//注意大小为4的sz可能没有被填满,因为定界符不被get读取,所以要跳过
if (ifs.peek () == '\n')//读当前位置的字符,但不改变文件位置
ifs.ignore ();//掠过当前位置的字符,文件位置后移
}
if (! ifs.eof ())//当前是否到了文件结尾
cerr << "Cannot read input file 1" << endl;
ifs.clear ();
(3).getline():可以自动掠过定界符,但当其试图读取第二个参数-1个字符时会发生错误
因为当文件结束的时候,可能没有填满第二个参数-1个字符,这时又结束了(读取不到字符),那么就会出错
char szLarge[8];
while (ifs.getline (szLarge, sizeof (szLarge), '\n'))
cout << szLarge;
if (! ifs.eof ())//当前是否到了文件结尾
cerr << "Cannot read input file" << endl;
8.字节流:
read(char*, size_t)/write(char*, size_t)
如:
char caBuffer[256];
while (ifs.read (cbBuffer, sizeof (cbBuffer)){
ofs.write (cbBuffer, sizeof (cbBuffer));
}
//可通过gcount()函数推断出实际读到byBuffer缓冲区中的字节数。
if (ifs.eof ())//进入某种错误状态时亦返回false
ofs.write (cbBuffer, ifs.gcount ());
else
cerr << "error!" << endl;
9.流函数:
#include <math.h>
#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;
int main (int argc, char* argv[]) {
cout << sqrt (2) << endl;//1.41421
cout.precision (10);//设置小数点精度,区别不带参数的函数(返回精度)
cout << sqrt (2) << endl;//1.414213562
cout << setprecision (10) << sqrt (2) << endl;//1.414213562
cout << sqrt (2) << endl;//1.414213562
cout << cout.precision () << endl;//10
cout << setprecision (2) << 1.24 << ", " << 1.25 << ", " << 1.26 << endl;//1.2, 1.3, 1.3
cout << oct << 127 << endl;//177
cout << hex << 127 << endl;//7f
cout << dec << 127 << endl;//127
cout << setw (7)/*注意这个函数不保存到下面的设置*/ << oct << 127 << endl;//177
cout << setw (7) << hex << 127 << endl;//7f
cout << setw (7) << dec << 127 << endl;//127
//流控制符
cout << setfill ('#') << setw (7) << oct << 127 << endl;//####177
cout << setfill ('@') << setw (7) << hex << 127 << endl;//@@@@@7f
cout << setfill ('%') << setw (7) << dec << 127 << endl;//%%%%127
cout << left << setfill ('#') << setw (7) << oct << 127 << endl;//177####
cout << left << setfill ('@') << setw (7) << hex << 127 << endl;//7f@@@@@
cout << left << setfill ('%') << setw (7) << dec << 127 << endl;//127%%%%
cout << showbase << oct << 127 << endl;//0177
cout << hex << 127 << endl;//0x7f
cout << dec << 127 << endl;//127
cout << noshowbase << oct << 127 << endl;//177
cout << dec << 127 << endl;//127
cout << 12.00 << endl;//12
cout << setprecision (10) << showpoint << 12.00 << endl;//12.00000000
cout.setf (ios::showpoint);//显示后面的0
cout << 12.00 << endl;//12.00000000
cout.precision (4);
cout << sqrt (200) << endl;//14.14
cout.setf (ios::scientific);/*精度所限制的实际上只是底数小数部分的显示位数*/
cout << sqrt (200) << endl;//1.4142e+001
ifstream ifs ("ex04.txt");
ifs.unsetf (ios::skipws);/*跳过空白字符(空格符、制表符以及换行 符等),
但如果出于某种原因,我们不希望忽略输入流中的空白字符,
那么我们就可以使用控制符noskipws或者调用输入流的unsetf(ios::skipws)成员函数。
我们也可以使用操纵子skipws来取消noskipws的效果,或者调
用输入流的setf(ios::skipws)成员函数达到同样的目的*/
char c;
while (ifs >> c)
cout << c;
return 0;
}
10.字符串流:
(1)ostringstream对象的一个优点是,可以利用输出操作符“<<”的格式化能力把数值类型的数据转换为它们的字符串表示形式
(2)另外:格式化字符数组
char s[1024];
sprintf (s, "money = %.2f\n", 23.44);
本文出自 “BaggerSky” 博客,谢绝转载!