IO流总结

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);


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章