POCO C++库学习和分析 -- 流 (一)

POCO C++库学习和分析 -- 流 (一)



          流(Stream)是C++和C之间的一大区别。写C++的程序员都知道流的用法。在Poco库中,在标准流的基础上又扩充了一些流,分别是基于Base64和HexBinary的编解码流,使用zlib的数据压缩流,二进制的I/O流,文件流,以及一些其他的辅助流;另外Poco库还提供了一个扩展的结构,用于创建用户自定义流。

          Poco库中所有的流类都与标准c++库中的流兼容。并且在Poco库中,大多数流都仅仅是个过滤器,这意味着它们不会直接从设备中读取或者写入数据,通常情况下它们会链接到另一个流上。下面我们分别对它们进行介绍。


1. 标准c++流介绍

          在介绍Poco的流之前,我觉得有必要了解C++中的输入输出流,不然就会觉得Poco中的流很难理解。在看完C++的流结构后,自然会对Poco库中的流内容豁然开朗。我也一样。
          为了保证语言和平台无关,C++和C一样,不具备内部输入输出能力。语言的输入输出能力是和操作系统相关的,在最底层都是通过调用操作系统的I/O库实现。

          在C++的iostream流库中,存在着两个基本部分。分别是:
          1. 流:C++把输入和输出看作字节流。输入时,程序从输出流中抽取字节;输出时,程序将字节插入到输出流中。流充当了程序和流源或者流目标之间的桥梁。
          2. 缓冲区:缓冲区是用作中介的内存块,它是将信息从设备传输到程序或者从程序传输到设备的临时存储工具,用以匹配程序和设备之间速度的差距。从设计上说,增加了缓冲区,使的C++的iostream结构更具有扩展性。

          C++的 输入输出类图:
POCO C++库学习和分析 -- 流 (一)_第1张图片



          下面对C++中各个流类的介绍主要来自于wiki以及网站 cplusplus。


1.1 ios_base

          ios_base类封装了C++标准中的流,并定义了在输入输出中不依赖于读写的数据类型的基本信息和行为,如格式化信息、异常状态、事件回调等。

          在类std::ios_base中,保存了下述关于流的信息:
          格式控制信息的枚举类型fmtflags ,影响到如何解释输入串行的格式、如何生成输出串行的格式,例如整数是用16进制还是10进制表示,浮点数是科学计数法还是定点形式;
          流的状态枚举类型iostate,如数据是否完整、是否到达流的末尾、是否读写失败等;
          流的打开方式枚举类型openmode,如读取、写入、追加、创建时删除原内容、二进制打开、
          流的定位位置枚举类型seekdir,如开始位置、当前位置、结尾位置等。
          流的事件枚举类型event,如“擦除”事件erase_event,改变locale设置事件imbue_event,复制格式事件copyfmt_event。
          流的私有的其它额外保存的数据,为一个long型数组与一个指针数组。
          一个成员类failure,用于作为C++标准中,流输入输出类库抛出的各种异常的基类。
          一个成员类Init,用于封装cout、cin、wcout等8个静态对象的初始化函数。

          成员函数包括:

          格式化:

          1. 读取/设置流的格式

fmtflags flags() const;
fmtflags flags (fmtflags fmtfl);
  例子:
// modify flags
#include <iostream>     // std::cout, std::ios

int main () {
  std::cout.flags ( std::ios::right | std::ios::hex | std::ios::showbase );
  std::cout.width (10);
  std::cout << 100 << '\n';
  return 0;
}


          2. 设置流的格式,与原有格式合并
fmtflags setf (fmtflags fmtfl);
fmtflags setf (fmtflags fmtfl, fmtflags mask);
  例子:
// modifying flags with setf/unsetf
#include <iostream>     // std::cout, std::ios

int main () {
  std::cout.setf ( std::ios::hex, std::ios::basefield );  // set hex as the basefield
  std::cout.setf ( std::ios::showbase );                  // activate showbase
  std::cout << 100 << '\n';
  std::cout.unsetf ( std::ios::showbase );                // deactivate showbase
  std::cout << 100 << '\n';
  return 0;
}
输出:
         Output:
         0x64
         64


          3. 根据参数mask,清除流的格式的某些位(bit)
void unsetf (fmtflags mask);
  例子:
// modifying flags with setf/unsetf
#include <iostream>     // std::cout, std::ios

int main () {
  std::cout.setf ( std::ios::hex, std::ios::basefield );  // set hex as the basefield
  std::cout.setf ( std::ios::showbase );                  // activate showbase
  std::cout << 100 << '\n';
  std::cout.unsetf ( std::ios::showbase );                // deactivate showbase
  std::cout << 100 << '\n';
  return 0;
}
输出:
         0x64
         64


          4. 读取/设置显示浮点数时的精度
streamsize precision() const;
streamsize precision (streamsize prec);
  例子:
// modify precision
#include <iostream>     // std::cout, std::ios

int main () {
  double f = 3.14159;
  std::cout.unsetf ( std::ios::floatfield );                // floatfield not set
  std::cout.precision(5);
  std::cout << f << '\n';
  std::cout.precision(10);
  std::cout << f << '\n';
  std::cout.setf( std::ios::fixed, std:: ios::floatfield ); // floatfield set to fixed
  std::cout << f << '\n';
  return 0;
}
输出:
         3.1416
         3.14159
         3.1415900000


          5. 读取/设定流的输出数据的显示宽度
streamsize width() const;
streamsize width (streamsize wide);
  例子:
// field width
#include <iostream>     // std::cout, std::left

int main () {
  std::cout << 100 << '\n';
  std::cout.width(10);
  std::cout << 100 << '\n';
  std::cout.fill('x');
  std::cout.width(15);
  std::cout << std::left << 100 << '\n';
  return 0;
}
输出:
         100
                100
         100xxxxxxxxxxxx


           语言环境:
          1. 给流设置本地语言环境
locale imbue (const locale& loc);
  例子:
// imbue example
#include <iostream>     // std::cout
#include <locale>       // std::locale

int main()
{
  std::locale mylocale("");   // get global locale
  std::cout.imbue(mylocale);  // imbue global locale
  std::cout << 3.14159 << '\n';
  return 0;
}

输出:

         3,14159


          2. 获取当前使用语言环境
locale getloc() const;

1.2 basic_ios

          basic_ios定义出“与字符类型及其相应字符特性相关”的stream class的共同属性,其中包括清除流状态、设置流状态、拷贝流标志、返回或设置流缓冲区指针、设置本地化相关信息、返回或设置填充字符、字符转换,还包括了stream所用的缓冲器.
          basic_ios在其内部定义了一个指向streambuf的指针。
template <class Elem, class Traits>
class basic_ios
     : public ios_base
{
     //C++标准库封装了一个缓冲区类streambuf,以供输入输出流对象使用。
     //每个标准C++输出输出流对象都包含一个指向streambuf的指针,
     basic_streambuf<_Elem, _Traits>*_Mystrbuf;


     // ....
}


           成员函数包括:

         1. 状态标记函数:
bool good() const; //检查流状态位是否为good
bool eof() const; //检查流状态位是否为eof,eofbit位被标志
bool fail() const; //检查流状态位是否为fail,failbit或者badbit被标志
bool bad() const; //检查流状态位是否为bad,badbit位被标志
iostate rdstate() const; //返回流状态位

          有两种方法可以获得输入/输出的状态信息。一种方法是通过调用rdstate()函数,它返回当前状态的错误标记。另一种方法则是使用good(), eof(),fail(), bad()函数来检测相应的输入/输出状态。
          状态位和函数返回值关系如下表:


iostate value
(member constant)
indicates functions to check state flags
good() eof() fail() bad() rdstate()
goodbit No errors (zero value iostate) true false false false goodbit
eofbit End-of-File reached on input operation false true false false eofbit
failbit Logical error on i/o operation false false true false failbit
badbit Read/writing error on i/o operation false false true true badbit


         例子:

// error state flags
#include <iostream>     // std::cout, std::ios
#include <sstream>      // std::stringstream

void print_state (const std::ios& stream) {
  std::cout << " good()=" << stream.good();
  std::cout << " eof()=" << stream.eof();
  std::cout << " fail()=" << stream.fail();
  std::cout << " bad()=" << stream.bad();
}

int main () {
  std::stringstream stream;

  stream.clear (stream.goodbit);
  std::cout << "goodbit:"; print_state(stream); std::cout << '\n';

  stream.clear (stream.eofbit);
  std::cout << " eofbit:"; print_state(stream); std::cout << '\n';

  stream.clear (stream.failbit);
  std::cout << "failbit:"; print_state(stream); std::cout << '\n';

  stream.clear (stream.badbit);
  std::cout << " badbit:"; print_state(stream); std::cout << '\n';

  return 0;
}
输出:
         goodbit: good()=1 eof()=0 fail()=0 bad()=0
         eofbit: good()=0 eof()=1 fail()=0 bad()=0
         failbit: good()=0 eof()=0 fail()=1 bad()=0
         badbit: good()=1 eof()=0 fail()=1 bad()=1


         2. oprator!()
bool operator!() const;
         如果没有错误标记被设置(failbit或badbit),返回true,否则返回false


         3. 设置/清除状态
void setstate (iostate state);
void clear (iostate state = goodbit);
         有两种方法可以设置输入/输出的状态信息。clear()函数可以使流状态将按照ios_base::iostate所描述的样子进行设置。ios::failbit、ios::badbit、ios::eofbit、ios::goodbit均为常量,它们中的任何一个都代表了一种流状态,或可被称为“输入状态标记位常量”。它们不是failbit、badbit、eofbit、goodbit这四个标记位的存贮变量。标记为常量的状态如上表所述。

         clear() 函数作用是:将流状态设置成括号内参数所代表的状态,强制覆盖掉流的原状态。

         例子:

// clearing errors
#include <iostream>     // std::cout
#include <fstream>      // std::fstream

int main () {
  char buffer [80];
  std::fstream myfile;

  myfile.open ("test.txt",std::fstream::in);

  myfile << "test";
  if (myfile.fail())
  {
    std::cout << "Error writing to test.txt\n";
    myfile.clear();
  }

  myfile.getline (buffer,80);
  std::cout << buffer << " successfully read from file.\n";

  return 0;
}

         setstate()函数的作用是:它并不强制覆盖流的原状态,而是将括号内参数所代表的状态叠加到原始状态上。它相当于:
void basic_ios::setstate (iostate state) {
  clear(rdstate()|state);
}


         4. 拷贝格式:
basic_ios& copyfmt (const basic_ios& rhs);

         例子:
// copying formatting information
#include <iostream>     // std::cout
#include <fstream>      // std::ofstream

int main () {
  std::ofstream filestr;
  filestr.open ("test.txt");

  std::cout.fill ('*');
  std::cout.width (10);
  filestr.copyfmt (std::cout);

  std::cout << 40;
  filestr << 40;

  return 0;
}


         5. 设置或获取填充字符
char_type fill() const;
char_type fill (char_type fillch);

         例子:
// using the fill character
#include <iostream>     // std::cout

int main () {
  char prev;

  std::cout.width (10);
  std::cout << 40 << '\n';

  prev = std::cout.fill ('x');
  std::cout.width (10);
  std::cout << 40 << '\n';

  std::cout.fill(prev);

  return 0;
}
输出:
                 40
         xxxxxxxx40


         6. 返回和设置当前流的异常标志
iostate exceptions() const;
void exceptions (iostate except);

         例子:
// basic_ios::exceptions
#include <iostream>     // std::cerr
#include <fstream>      // std::ifstream

int main () {
  std::ifstream file;
  file.exceptions ( std::ifstream::failbit | std::ifstream::badbit );
  try {
    file.open ("test.txt");
    while (!file.eof()) file.get();
  }
  catch (std::ifstream::failure e) {
    std::cerr << "Exception opening/reading file";
  }

  file.close();

  return 0;
}


         7. 返回和设置绑定的输出流(绑定流是一个输出流,输出流将在流的每一次I/O操作前先被输出)。“绑定”的效果也就相当于,每当被“绑定”的对象有输入或输出操作时,会先自动刷新“绑定”对象的缓冲区,以达到实时的效果。
basic_ostream<char_type,traits_type>* tie() const;
basic_ostream<char_type,traits_type>* tie (basic_ostream<char_type,traits_type>* tiestr);

         例子:
// redefine tied object
#include <iostream>     // std::ostream, std::cout, std::cin
#include <fstream>      // std::ofstream

int main () {
  std::ostream *prevstr;
  std::ofstream ofs;
  ofs.open ("test.txt");

  std::cout << "tie example:\n";

  *std::cin.tie() << "This is inserted into cout";
  prevstr = std::cin.tie (&ofs);
  *std::cin.tie() << "This is inserted into the file";
  std::cin.tie (prevstr);

  ofs.close();

  return 0;
}
输出:
         tie example:
         This is inserted into cout


         8. 返回或设置流缓冲区指针。用户可以通过调用rdbuf()成员函数获得该指针,从而直接访问底层streambuf对象。因此,可以直接对底层缓冲区进行数据读写,从而跳过上层的格式化输入输出操作。
basic_streambuf<char_type,traits_type>* rdbuf() const;
basic_streambuf<char_type,traits_type>* rdbuf (basic_streambuf<char_type,traits_type>* sb);

         例子:
// redirecting cout's output thrrough its stream buffer
#include <iostream>     // std::streambuf, std::cout
#include <fstream>      // std::ofstream

int main () {
  std::streambuf *psbuf, *backup;
  std::ofstream filestr;
  filestr.open ("test.txt");

  backup = std::cout.rdbuf();     // back up cout's streambuf

  psbuf = filestr.rdbuf();        // get file's streambuf
  std::cout.rdbuf(psbuf);         // assign streambuf to cout

  std::cout << "This is written to the file";

  std::cout.rdbuf(backup);        // restore cout's original streambuf

  filestr.close();

  return 0;
}


         9. 字符转换
         返回宽字符wc对应的字符dfault,在其内部使用了流对应的locale对象做转换
char narrow (char_type wc, char dfault) const;
         返回c对应的宽字符
char_type widen (char c) const;


1.3  输入流( istream)

         istream是普通输入流类和用于其它输入流的基类。

         输入流的成员函数包括:

         1. 构造函数
explicit istream (streambuf* sb);

         例子:
// istream constructor
#include <iostream>     // std::ios, std::istream, std::cout
#include <fstream>      // std::filebuf


int main () {
  std::filebuf fb;
  if (fb.open ("test.txt",std::ios::in))
  {
    std::istream is(&fb);
    while (is)
      std::cout << char(is.get());
    fb.close();
  }
  return 0;
}

         2. 重载析取运算符
istream& operator>> (bool& val);
istream& operator>> (short& val);
istream& operator>> (unsigned short& val);
istream& operator>> (int& val);
istream& operator>> (unsigned int& val);
istream& operator>> (long& val);
istream& operator>> (unsigned long& val);
istream& operator>> (float& val);
istream& operator>> (double& val);
istream& operator>> (long double& val);
istream& operator>> (void*& val);
stream buffers (2)	
istream& operator>> (streambuf* sb );
manipulators (3)	
istream& operator>> (istream& (*pf)(istream&));
istream& operator>> (ios& (*pf)(ios&));
istream& operator>> (ios_base& (*pf)(ios_base&));

         例子:
// example on extraction
#include <iostream>     // std::cin, std::cout, std::hex

int main () {
  int n;

  std::cout << "Enter a number: ";
  std::cin >> n;
  std::cout << "You have entered: " << n << '\n';

  std::cout << "Enter a hexadecimal number: ";
  std::cin >> std::hex >> n;         // manipulator
  std::cout << "Its decimal equivalent is: " << n << '\n';

  return 0;
}

         3. 无格式输入:
streamsize gcount() const;
         获取最后一次执行析取操作所读取的字符串数目

         例子:

// cin.gcount example
#include <iostream>     // std::cin, std::cout

int main () {
  char str[20];

  std::cout << "Please, enter a word: ";
  std::cin.getline(str,20);
  std::cout << std::cin.gcount() << " characters read: " << str << '\n';

  return 0;
}
输出:
         Please, enter a word: simplify
         9 characteres read: simplify


         4. 从流中以无格式输入方式析取字符串
int get()
istream& get (char& c)
istream& get (char* s, streamsize n)
istream& get (char* s, streamsize n, char delim)
istream& get (streambuf& sb)
istream& get (streambuf& sb, char delim)

         例子:
// istream::get example
#include <iostream>     // std::cin, std::cout
#include <fstream>      // std::ifstream

int main () {
  char str[256];

  std::cout << "Enter the name of an existing text file: ";
  std::cin.get (str,256);    // get c-string

  std::ifstream is(str);     // open file

  while (is.good())          // loop while extraction from file is possible
  {
    char c = is.get();       // get character from file
    if (is.good())
      std::cout << c;
  }

  is.close();                // close file

  return 0;
}


         5. 从流中以无格式输入方式析取字符串(直至提取到指定的分隔字符,或已向流中写入最大长度的n个字符(包括终止空字符)),并存储内容进入c风格的字符串中。
istream& getline (char* s, streamsize n );
istream& getline (char* s, streamsize n, char delim );

         例子:
// istream::getline example
#include <iostream>     // std::cin, std::cout

int main () {
  char name[256], title[256];

  std::cout << "Please, enter your name: ";
  std::cin.getline (name,256);

  std::cout << "Please, enter your favourite movie: ";
  std::cin.getline (title,256);

  std::cout << name << "'s favourite movie is " << title;

  return 0;
}

         6. 从流中提取字符输入序列(直到n个字符被提取,或遇见一个指定的字符分隔符),并丢弃。
istream& ignore (streamsize n = 1, int delim = EOF);

         例子:
// istream::ignore example
#include <iostream>     // std::cin, std::cout

int main () {
  char first, last;

  std::cout << "Please, enter your first name followed by your surname: ";

  first = std::cin.get();     // get one character
  std::cin.ignore(256,' ');   // ignore until space

  last = std::cin.get();      // get one character

  std::cout << "Your initials are " << first << last << '\n';

  return 0;
}


         7. 返回输入序列中的下一个字符,但不析取:字符将在下一次析取操作中从流中提取。
int peek();

         例子:
// istream::peek example
#include <iostream>     // std::cin, std::cout
#include <string>       // std::string


int main () {

  std::cout << "Please, enter a number or a word: ";
  char c = std::cin.peek();

  if ( (c >= '0') && (c <= '9') )
  {
    int n;
    std::cin >> n;
    std::cout << "You entered the number: " << n << '\n';
  }
  else
  {
    std::string str;
    std::getline (std::cin, str);
    std::cout << "You entered the word: " << str << '\n';
  }

  return 0;
}
输出:
         Please, enter a number or a word: foobar
         You entered the word: foobar


         8. 从流中析取n个字符,并把它们存储到s指向的字符数组
istream& read (char* s, streamsize n);

         例子:
// read a file into memory
#include <iostream>     // std::cout
#include <fstream>      // std::ifstream

int main () {
  std::ifstream is ("test.txt", std::ifstream::binary);
  if (is) {
    // get length of file:
    is.seekg (0, is.end);
    int length = is.tellg();
    is.seekg (0, is.beg);

    char * buffer = new char [length];

    std::cout << "Reading " << length << " characters... ";
    // read data as a block:
    is.read (buffer,length);

    if (is)
      std::cout << "all characters read successfully.";
    else
      std::cout << "error: only " << is.gcount() << " could be read";
    is.close();

    // ...buffer contains the entire file...

    delete[] buffer;
  }
  return 0;
}
输出:
         Reading 640 characters... all characters read successfully.


         9. 从流中析取n个字符,并把它们存储到s指向的字符数组。在内部关联的缓冲区(如果存在的话)用完时,操作返回,即使文件结束字符尚未达到。这个函数主要用于从某些类型的异步源中读取数据。由于析取操作会在内部缓冲区耗尽时终止,从而避免了潜在的延时。
streamsize readsome (char* s, streamsize n);

         10. 把指定字符还给输入流,使得字符能够被重新析取
istream& putback (char c);

         例子:
// istream::putback example
#include <iostream>     // std::cin, std::cout
#include <string>       // std::string

int main () {
  std::cout << "Please, enter a number or a word: ";
  char c = std::cin.get();

  if ( (c >= '0') && (c <= '9') )
  {
    int n;
    std::cin.putback (c);
    std::cin >> n;
    std::cout << "You entered a number: " << n << '\n';
  }
  else
  {
    std::string str;
    std::cin.putback (c);
    getline (std::cin,str);
    std::cout << "You entered a word: " << str << '\n';
  }
  return 0;
}
输出:
         Please, enter a number or a word: pocket
         You entered a word: pocket


         11. 把上一个析取的字符还给输入流,使得字符能够被重新析取
istream& unget();

         例子:
// istream::unget example
#include <iostream>     // std::cin, std::cout
#include <string>       // std::string

int main () {
  std::cout << "Please, enter a number or a word: ";
  char c = std::cin.get();

  if ( (c >= '0') && (c <= '9') )
  {
    int n;
    std::cin.unget();
    std::cin >> n;
    std::cout << "You entered a number: " << n << '\n';
  }
  else
  {
    std::string str;
    std::cin.unget();
    getline (std::cin,str);
    std::cout << "You entered a word: " << str << '\n';
  }
  return 0;
}
输出:
         Please, enter a number or a word: 7791
         You entered a number: 7791


         12. 返回当前输入流字符的位置:
streampos tellg();

         例子:
// read a file into memory
#include <iostream>     // std::cout
#include <fstream>      // std::ifstream

int main () {
  std::ifstream is ("test.txt", std::ifstream::binary);
  if (is) {
    // get length of file:
    is.seekg (0, is.end);
    int length = is.tellg();
    is.seekg (0, is.beg);

    // allocate memory:
    char * buffer = new char [length];

    // read data as a block:
    is.read (buffer,length);

    is.close();

    // print content:
    std::cout.write (buffer,length);

    delete[] buffer;
  }

  return 0;
}


         13. 设置下一个析取字符串在输入流中的位置
istream& seekg (streampos pos);
istream& seekg (streamoff off, ios_base::seekdir way);


         同步
         1. 同步流相关的缓冲区buf
int sync();

  例子:
// syncing input stream
#include <iostream>     // std::cin, std::cout

int main () {
  char first, second;

  std::cout << "Please, enter a word: ";
  first = std::cin.get();
  std::cin.sync();

  std::cout << "Please, enter another word: ";
  second = std::cin.get();

  std::cout << "The first word began by " << first << '\n';
  std::cout << "The second word began by " << second << '\n';

  return 0;
}
输出:
         Please, enter a word: test
         Please enter another word: text
         The first word began by t
         The second word began by t


1.4. 输出流(ostream)

         ostream是普通输出流类和用于其它输出流类的基类。

         1. 构造函数
explicit ostream (streambuf* sb);

         例子:
// ostream constructor
#include <iostream>     // std::cout, std::ostream, std::ios
#include <fstream>      // std::filebuf

int main () {
  std::filebuf fb;
  fb.open ("test.txt",std::ios::out);
  std::ostream os(&fb);
  os << "Test sentence\n";
  fb.close();
  return 0;
}


         2. 重载插入运算符
ostream& operator<< (bool val);
ostream& operator<< (short val);
ostream& operator<< (unsigned short val);
ostream& operator<< (int val);
ostream& operator<< (unsigned int val);
ostream& operator<< (long val);
ostream& operator<< (unsigned long val);
ostream& operator<< (float val);
ostream& operator<< (double val);
ostream& operator<< (long double val);
ostream& operator<< (void* val);
ostream& operator<< (streambuf* sb );	
ostream& operator<< (ostream& (*pf)(ostream&));
ostream& operator<< (ios& (*pf)(ios&));
ostream& operator<< (ios_base& (*pf)(ios_base&));

         例子:
// example on insertion
#include <iostream>     // std::cout, std::right, std::endl
#include <iomanip>      // std::setw

int main () {
  int val = 65;

  std::cout << std::right;       // right-adjusted (manipulator)
  std::cout << std::setw(10);    // set width (extended manipulator)

  std::cout << val << std::endl; // multiple insertions

  return 0;
}
输出:
        65


          无格式输出
         1. 把字符c插入流中
ostream& put (char c);

         例子:
// typewriter
#include <iostream>     // std::cin, std::cout
#include <fstream>      // std::ofstream

int main () {
  std::ofstream outfile ("test.txt");
  char ch;

  std::cout << "Type some text (type a dot to finish):\n";
  do {
    ch = std::cin.get();
    outfile.put(ch);
  } while (ch!='.');

  return 0;
}


         2. 插入字符数组s的前n个字符进入流中
ostream& write (const char* s, streamsize n);

         例子:
// Copy a file
#include <fstream>      // std::ifstream, std::ofstream

int main () {
  std::ifstream infile ("test.txt",std::ifstream::binary);
  std::ofstream outfile ("new.txt",std::ofstream::binary);

  // get size of file
  infile.seekg (0,infile.end);
  long size = infile.tellg();
  infile.seekg (0);

  // allocate memory for file content
  char* buffer = new char[size];

  // read content of infile
  infile.read (buffer,size);

  // write to outfile
  outfile.write (buffer,size);

  // release dynamically-allocated memory
  delete[] buffer;

  outfile.close();
  infile.close();
  return 0;
}

         3. 定位:
         给出当前字符在输出流中的位置
streampos tellp();

         例子:
// position in output stream
#include <fstream>      // std::ofstream

int main () {
  std::ofstream outfile;
  outfile.open ("test.txt");

  outfile.write ("This is an apple",16);
  long pos = outfile.tellp();
  outfile.seekp (pos-7);
  outfile.write (" sam",4);

  outfile.close();

  return 0;
}
输出:
         This is a sample


         4. 设置下一个在流中被插入字符的位置
ostream& seekp (streampos pos);	
ostream& seekp (streamoff off, ios_base::seekdir way);

         ios_base::seekdir定义:

member constant seeking relative to
beg beginning of sequence.
cur current position within sequence.
end end of sequence.


         例子:
// position in output stream
#include <fstream>      // std::ofstream


int main () {

  std::ofstream outfile;
  outfile.open ("test.txt");

  outfile.write ("This is an apple",16);
  long pos = outfile.tellp();
  outfile.seekp (pos-7);
  outfile.write (" sam",4);

  outfile.close();

  return 0;
}


         同步:
         1. 同步关联的输出缓冲数据进入流
ostream& flush();

         例子:
// Flushing files
#include <fstream>      // std::ofstream

int main () {

  std::ofstream outfile ("test.txt");

  for (int n=0; n<100; ++n)
  {
    outfile << n;
    outfile.flush();
  }
  outfile.close();

  return 0;
}


1.5. 输入输出流(iostream)

         iostream从ostream和istream继承,是普通输入输出流类和用于其它输入输出流的基类。iostream的接口包括了所有的ostream和istream接口。


1.6. 输出文件流类(ofstream)

         1. 构造函数:
ofstream();
explicit ofstream (const char* filename, ios_base::openmode mode = ios_base::out);
         
         例子:
// ofstream constructor.
#include <fstream>      // std::ofstream

int main () {

  std::ofstream ofs ("test.txt", std::ofstream::out);

  ofs << "lorem ipsum";

  ofs.close();

  return 0;
}

          成员函数:
         1. 打开文件
void open (const char* filename,  ios_base::openmode mode = ios_base::out);

         mode
member constant stands for access
in input File open for reading: the internal stream buffer supports input operations.
out output File open for writing: the internal stream buffer supports output operations.
binary binary Operations are performed in binary mode rather than text.
ate at end The output position starts at the end of the file.
app append All output operations happen at the end of the file, appending to its existing contents.
trunc truncate Any contents that existed in the file before it is open are discarded.


         插一句:app模式下,写指针每次都会在文件结尾,ate模式则只在打开时才将写指针置于文件末尾。ate赋予了程序员修改文件内容的能力。流seekp的能力是依赖于流内部缓冲区实现的。也就说如果不赋予流读文件的能力,没有读的缓冲区,流就无法seekp到文件的任意位置。所以想要定位到文件某一位置,对文件进行修改,要如下打开文件:
fstream(filename, ios::in|ios::out|ios::ate)。

         例子:
// ofstream::open / ofstream::close
#include <fstream>      // std::ofstream


int main () {

  std::ofstream ofs;
  ofs.open ("test.txt", std::ofstream::out | std::ofstream::app);

  ofs << " more lorem ipsum";

  ofs.close();

  return 0;
}


         2. 确认文件是否打开
bool is_open();
         在函数内部调用rdbuf()->is_open();

         例子:
// ofstream::is_open
#include <iostream>     // std::cout
#include <fstream>      // std::ofstream

int main () {
  std::ofstream ofs;
  ofs.open ("test.txt");
  if (ofs.is_open())
  {
    ofs << "lorem ipsum";
    std::cout << "Output operation successfully performed\n";
    ofs.close();
  }
  else
  {
    std::cout << "Error opening file";
  }
  return 0;
}
输出:
         Output operation successfully performed


         3. 关闭当前同流关联的文件
void close();

         例子:
// ofstream::open / ofstream::close
#include <fstream>      // std::ofstream

int main () {

  std::ofstream ofs;
  ofs.open ("test.txt", std::ofstream::out | std::ofstream::app);

  ofs << " more lorem ipsum";

  ofs.close();

  return 0;
}


         4. 获取内部的文件流缓冲对象的指针
filebuf* rdbuf() const;

         例子:
// copy a file using file stream buffers
#include <fstream>      // std::filebuf, std::ifstream, std::ofstream
#include <cstdio>       // EOF


int main () {
  std::ifstream ifs ("test.txt");
  std::ofstream ofs ("copy.txt");

  std::filebuf* inbuf  = ifs.rdbuf();
  std::filebuf* outbuf = ofs.rdbuf();

  char c = inbuf->sbumpc();
  while (c != EOF)
  {
    outbuf->sputc (c);
    c = inbuf->sbumpc();
  }

  ofs.close();
  ifs.close();

  return 0;
}


1.7. 输入文件流类(ifstream)

         1. 构造函数:
ifstream();	
explicit ifstream (const char* filename, ios_base::openmode mode = ios_base::in);

         例子:
// ifstream constructor.
#include <iostream>     // std::cout
#include <fstream>      // std::ifstream

int main () {

  std::ifstream ifs ("test.txt", std::ifstream::in);

  char c = ifs.get();

  while (ifs.good()) {
    std::cout << c;
    c = ifs.get();
  }

  ifs.close();

  return 0;
}


         成员函数:

         1. 打开文件
void open (const char* filename,  ios_base::openmode mode = ios_base::in);

         例子:
// print the content of a text file.
#include <iostream>     // std::cout
#include <fstream>      // std::ifstream

int main () {
  std::ifstream ifs;

  ifs.open ("test.txt", std::ifstream::in);

  char c = ifs.get();

  while (ifs.good()) {
    std::cout << c;
    c = ifs.get();
  }

  ifs.close();

  return 0;
}


         2. 是否文件打开
bool is_open();

         例子:
// ifstream::is_open
#include <iostream>     // std::cout
#include <fstream>      // std::ifstream

int main () {
  std::ifstream ifs ("test.txt");

  if (ifs.is_open()) {
    // print file:
    char c = ifs.get();
    while (ifs.good()) {
      std::cout << c;
      c = ifs.get();
    }
  }
  else {
    // show message:
    std::cout << "Error opening file";
  }

  return 0;
}


         3. 关闭流关联的文件
void close();

         例子:
// print the content of a text file.
#include <iostream>     // std::cout
#include <fstream>      // std::ifstream

int main () {
  std::ifstream ifs;

  ifs.open ("test.txt");

  char c = ifs.get();

  while (ifs.good()) {
    std::cout << c;
    c = ifs.get();
  }

  ifs.close();

  return 0;
}


         4. 获取内部关联的文件缓冲区指针
filebuf* rdbuf() const;

         例子:
// read file data using associated buffer's members
#include <iostream>     // std::cout
#include <fstream>      // std::filebuf, std::ifstream


int main () {
  std::ifstream ifs ("test.txt", std::ifstream::binary);

  // get pointer to associated buffer object
  std::filebuf* pbuf = ifs.rdbuf();

  // get file size using buffer's members
  std::size_t size = pbuf->pubseekoff (0,ifs.end,ifs.in);
  pbuf->pubseekpos (0,ifs.in);

  // allocate memory to contain file data
  char* buffer=new char[size];

  // get file data
  pbuf->sgetn (buffer,size);

  ifs.close();

  // write content to stdout
  std::cout.write (buffer,size);

  delete[] buffer;

  return 0;
}


1.8. 输入输出文件流(fstream)

         fstream从ofstream和ifstream继承,其接口包括了所有的ofstream和ifstream接口。


1.9. 输出串流类(ostringstream)

         1. 构造函数:
explicit ostringstream (ios_base::openmode which = ios_base::out);	
explicit ostringstream (const string& str, ios_base::openmode which = ios_base::out);

         例子:
// ostringstream constructor
#include <iostream>     // std::cout, std::ios
#include <sstream>      // std::ostringstream

int main () {
  std::ostringstream foo;                            // out
  std::ostringstream bar (std::ostringstream::ate);  // out|ate

  foo.str("Test string");
  bar.str("Test string");

  foo << 101;
  bar << 101;

  std::cout << foo.str() << '\n';
  std::cout << bar.str() << '\n';
  return 0;
}
输出:
         101t string
         Test string101


         成员函数:

         1.得到或获得字符串
string str() const;
void str (const string& s);

         例子:
// ostringstream::rdbuf
#include <string>       // std::string
#include <iostream>     // std::cout
#include <sstream>      // std::ostringstream


int main () {
  std::ostringstream oss;
  oss << "One hundred and one: " << 101;
  std::string s = oss.str();
  std::cout << s << '\n';
  return 0;
}

输出:

         One hundred and one: 101


         2. 插入操作符
ostream& operator<< (bool val);
ostream& operator<< (short val);
ostream& operator<< (unsigned short val);
ostream& operator<< (int val);
ostream& operator<< (unsigned int val);
ostream& operator<< (long val);
ostream& operator<< (unsigned long val);
ostream& operator<< (float val);
ostream& operator<< (double val);
ostream& operator<< (long double val);
ostream& operator<< (void* val);
ostream& operator<< (streambuf* sb );
ostream& operator<< (ostream& (*pf)(ostream&));
ostream& operator<< (ios& (*pf)(ios&));
ostream& operator<< (ios_base& (*pf)(ios_base&));

         例子:
// example on insertion
#include <iostream>     // std::cout, std::right, std::endl
#include <iomanip>      // std::setw

int main () {
  int val = 65;

  std::cout << std::right;       // right-adjusted (manipulator)
  std::cout << std::setw(10);    // set width (extended manipulator)

  std::cout << val << std::endl; // multiple insertions

  return 0;
}
输出:
        65


         3.插入字符c进入流
ostream& put (char c);

         例子:
// typewriter
#include <iostream>     // std::cin, std::cout
#include <fstream>      // std::ofstream

int main () {
  std::ofstream outfile ("test.txt");
  char ch;

  std::cout << "Type some text (type a dot to finish):\n";
  do {
    ch = std::cin.get();
    outfile.put(ch);
  } while (ch!='.');

  return 0;
}


         4.写字符串数组s的前n个字符进入流
ostream& write (const char* s, streamsize n);

         例子:
// Copy a file
#include <fstream>      // std::ifstream, std::ofstream

int main () {
  std::ifstream infile ("test.txt",std::ifstream::binary);
  std::ofstream outfile ("new.txt",std::ofstream::binary);

  // get size of file
  infile.seekg (0,infile.end);
  long size = infile.tellg();
  infile.seekg (0);

  // allocate memory for file content
  char* buffer = new char[size];

  // read content of infile
  infile.read (buffer,size);

  // write to outfile
  outfile.write (buffer,size);

  // release dynamically-allocated memory
  delete[] buffer;

  outfile.close();
  infile.close();
  return 0;
}


         5.获取当前字符在流中的位置
streampos tellp();

         例子:
// position in output stream
#include <fstream>      // std::ofstream

int main () {
  std::ofstream outfile;
  outfile.open ("test.txt");

  outfile.write ("This is an apple",16);
  long pos = outfile.tellp();
  outfile.seekp (pos-7);
  outfile.write (" sam",4);

  outfile.close();

  return 0;
}


         6.设置下一个插入字符在流中的位置
ostream& seekp (streampos pos);
ostream& seekp (streamoff off, ios_base::seekdir way);

         例子:
// position in output stream
#include <fstream>      // std::ofstream

int main () {

  std::ofstream outfile;
  outfile.open ("test.txt");

  outfile.write ("This is an apple",16);
  long pos = outfile.tellp();
  outfile.seekp (pos-7);
  outfile.write (" sam",4);

  outfile.close();

  return 0;
}
输出:
         This is a sample


         7.同步关联的流缓冲数据进入流
ostream& flush();

         例子:
// Flushing files
#include <fstream>      // std::ofstream

int main () {

  std::ofstream outfile ("test.txt");

  for (int n=0; n<100; ++n)
  {
    outfile << n;
    outfile.flush();
  }
  outfile.close();

  return 0;
}


1.10. 输入串流类(istringstream)


         1. 构造函数:
explicit istringstream (ios_base::openmode which = ios_base::in);	
explicit istringstream (const string& str, ios_base::openmode which = ios_base::in);

          例子:
// istringstream constructors.
#include <iostream>     // std::cout
#include <sstream>      // std::istringstream
#include <string>       // std::string

int main () {

  std::string stringvalues = "125 320 512 750 333";
  std::istringstream iss (stringvalues);

  for (int n=0; n<5; n++)
  {
    int val;
    iss >> val;
    std::cout << val*2 << '\n';
  }

  return 0;
}
输出:
         250
         640
         1024
         1500
         666


         成员函数:
         1. 获取设置内容
string str() const;
void str (const string& s);

         例子:
// istringstream::str
#include <string>       // std::string
#include <iostream>     // std::cout
#include <sstream>      // std::istringstream

int main () {
  std::istringstream iss;
  std::string strvalues = "32 240 2 1450";

  iss.str (strvalues);

  for (int n=0; n<4; n++)
  {
    int val;
    iss >> val;
    std::cout << val << '\n';
  }
  std::cout << "Finished writing the numbers in: ";
  std::cout << iss.str() << '\n';
  return 0;
}
输出:
         32
         240
         2
         1450
         Finished writing the numbers in: 32 240 2 1450


         2. 返回关联的内部缓冲区指针
stringbuf* rdbuf() const;

         例子:
// istringstream::rdbuf
#include <string>       // std::string
#include <iostream>     // std::cout
#include <sstream>      // std::istringstream, std::stringbuf

int main () {
  std::istringstream iss;
  std::stringbuf *pbuf = iss.rdbuf();

  // using stringbuf directly:
  pbuf->str("Example string");

  int size = pbuf->in_avail();

  while (pbuf->in_avail()>0)
    std::cout << static_cast<char>(pbuf->sbumpc());

  return 0;
}
输出:
         Example string


         3. 重载析取操作符
istream& operator>> (bool& val);
istream& operator>> (short& val);
istream& operator>> (unsigned short& val);
istream& operator>> (int& val);
istream& operator>> (unsigned int& val);
istream& operator>> (long& val);
istream& operator>> (unsigned long& val);
istream& operator>> (float& val);
istream& operator>> (double& val);
istream& operator>> (long double& val);
istream& operator>> (void*& val);
istream& operator>> (streambuf* sb );
istream& operator>> (istream& (*pf)(istream&));
istream& operator>> (ios& (*pf)(ios&));
istream& operator>> (ios_base& (*pf)(ios_base&));

         例子:
// example on extraction
#include <iostream>     // std::cin, std::cout, std::hex

int main () {
  int n;

  std::cout << "Enter a number: ";
  std::cin >> n;
  std::cout << "You have entered: " << n << '\n';

  std::cout << "Enter a hexadecimal number: ";
  std::cin >> std::hex >> n;         // manipulator
  std::cout << "Its decimal equivalent is: " << n << '\n';

  return 0;
}

         4. 返回最后一次无格式输入操作所析取的字符数量
streamsize gcount() const;

         例子:
// cin.gcount example
#include <iostream>     // std::cin, std::cout

int main () {
  char str[20];

  std::cout << "Please, enter a word: ";
  std::cin.getline(str,20);
  std::cout << std::cin.gcount() << " characters read: " << str << '\n';

  return 0;
}
输出:
         Please, enter a word: simplify
         9 characteres read: simplify


         5. 以无格式输入方式从输入流中析取字符
int get();
istream& get (char& c);
istream& get (char* s, streamsize n);
istream& get (char* s, streamsize n, char delim);	
istream& get (streambuf& sb);
istream& get (streambuf& sb, char delim);

         例子:
// istream::get example
#include <iostream>     // std::cin, std::cout
#include <fstream>      // std::ifstream

int main () {
  char str[256];

  std::cout << "Enter the name of an existing text file: ";
  std::cin.get (str,256);    // get c-string

  std::ifstream is(str);     // open file

  while (is.good())          // loop while extraction from file is possible
  {
    char c = is.get();       // get character from file
    if (is.good())
      std::cout << c;
  }

  is.close();                // close file

  return 0;
}


         6.以无格式输入方式从输入流中析取字符,并存储于c风格的字符串中。当析取字符是分割符或者已经析取了n个字符时,动作终止。默认情况下,分割符为"\n".
istream& getline (char* s, streamsize n );
istream& getline (char* s, streamsize n, char delim );

         例子:
// istream::getline example
#include <iostream>     // std::cin, std::cout

int main () {
  char name[256], title[256];

  std::cout << "Please, enter your name: ";
  std::cin.getline (name,256);

  std::cout << "Please, enter your favourite movie: ";
  std::cin.getline (title,256);

  std::cout << name << "'s favourite movie is " << title;

  return 0;
}


         7. 从流中提取字符输入序列(直到n个字符提取,或遇见一个指定的字符分隔字),并丢弃。
istream& ignore (streamsize n = 1, int delim = EOF);

         例子:
// istream::ignore example
#include <iostream>     // std::cin, std::cout

int main () {
  char first, last;

  std::cout << "Please, enter your first name followed by your surname: ";

  first = std::cin.get();     // get one character
  std::cin.ignore(256,' ');   // ignore until space

  last = std::cin.get();      // get one character

  std::cout << "Your initials are " << first << last << '\n';

  return 0;
}
输出:
         Please, enter your first name followed by your surname: John Smith
         Your initials are JS


         8. 返回输入序列中的下一个字符,但不析取:字符将在下一次析取操作中从流中提取。
int peek();

         例子:

// istream::peek example
#include <iostream>     // std::cin, std::cout
#include <string>       // std::string

int main () {

  std::cout << "Please, enter a number or a word: ";
  char c = std::cin.peek();

  if ( (c >= '0') && (c <= '9') )
  {
    int n;
    std::cin >> n;
    std::cout << "You entered the number: " << n << '\n';
  }
  else
  {
    std::string str;
    std::getline (std::cin, str);
    std::cout << "You entered the word: " << str << '\n';
  }

  return 0;
}
输出:
         Please, enter a number or a word: foobar
         You entered the word: foobar


         9. 从流中析取n个字符,并把它们存储入s指向的字符数组
istream& read (char* s, streamsize n);

         例子:
// read a file into memory
#include <iostream>     // std::cout
#include <fstream>      // std::ifstream

int main () {

  std::ifstream is ("test.txt", std::ifstream::binary);
  if (is) {
    // get length of file:
    is.seekg (0, is.end);
    int length = is.tellg();
    is.seekg (0, is.beg);

    char * buffer = new char [length];

    std::cout << "Reading " << length << " characters... ";
    // read data as a block:
    is.read (buffer,length);

    if (is)
      std::cout << "all characters read successfully.";
    else
      std::cout << "error: only " << is.gcount() << " could be read";
    is.close();

    // ...buffer contains the entire file...

    delete[] buffer;
  }
  return 0;
}
输出:
         Reading 640 characters... all characters read successfully.


         10. 从流中析取n个字符,并把它们存储入s指向的字符数组。在内部关联的缓冲区(如果存在的话)用完时,操作返回,即使此时尚未达到文件结束字符。这个函数主要用于从某些类型的异步源中读取数据。由于析取操作会在内部缓冲区耗尽时终止,从而避免了潜在的延时。
streamsize readsome (char* s, streamsize n);

         11. 把指定字符还给输入流,使得字符能够被重新析取
istream& putback (char c);

         例子:
// istream::putback example
#include <iostream>     // std::cin, std::cout
#include <string>       // std::string

int main () {
  std::cout << "Please, enter a number or a word: ";
  char c = std::cin.get();

  if ( (c >= '0') && (c <= '9') )
  {
    int n;
    std::cin.putback (c);
    std::cin >> n;
    std::cout << "You entered a number: " << n << '\n';
  }
  else
  {
    std::string str;
    std::cin.putback (c);
    getline (std::cin,str);
    std::cout << "You entered a word: " << str << '\n';
  }
  return 0;
}
输出:
         Please, enter a number or a word: pocket
         You entered a word: pocket


         12. 把上一次析取的字符还给输入流,使得字符能够被重新析取
istream& unget();

         例子:
// istream::unget example
#include <iostream>     // std::cin, std::cout
#include <string>       // std::string

int main () {
  std::cout << "Please, enter a number or a word: ";
  char c = std::cin.get();

  if ( (c >= '0') && (c <= '9') )
  {
    int n;
    std::cin.unget();
    std::cin >> n;
    std::cout << "You entered a number: " << n << '\n';
  }
  else
  {
    std::string str;
    std::cin.unget();
    getline (std::cin,str);
    std::cout << "You entered a word: " << str << '\n';
  }
  return 0;
}
输出:
         Please, enter a number or a word: 7791
         You entered a number: 7791


         13. 返回当前输入流字符的位置:
streampos tellg();

         例子:
// read a file into memory
#include <iostream>     // std::cout
#include <fstream>      // std::ifstream

int main () {
  std::ifstream is ("test.txt", std::ifstream::binary);
  if (is) {
    // get length of file:
    is.seekg (0, is.end);
    int length = is.tellg();
    is.seekg (0, is.beg);

    // allocate memory:
    char * buffer = new char [length];

    // read data as a block:
    is.read (buffer,length);

    is.close();

    // print content:
    std::cout.write (buffer,length);

    delete[] buffer;
  }

  return 0;
}


         14. 设置下一个析取字符串在输入流中的位置
istream& seekg (streampos pos);
istream& seekg (streamoff off, ios_base::seekdir way);

         例子:
// read a file into memory
#include <iostream>     // std::cout
#include <fstream>      // std::ifstream

int main () {
  std::ifstream is ("test.txt", std::ifstream::binary);
  if (is) {
    // get length of file:
    is.seekg (0, is.end);
    int length = is.tellg();
    is.seekg (0, is.beg);

    // allocate memory:
    char * buffer = new char [length];

    // read data as a block:
    is.read (buffer,length);

    is.close();

    // print content:
    std::cout.write (buffer,length);

    delete[] buffer;
  }

  return 0;
}


         15. 同步流相关的缓冲区buf
int sync();

         例子:
// syncing input stream
#include <iostream>     // std::cin, std::cout

int main () {
  char first, second;

  std::cout << "Please, enter a word: ";
  first = std::cin.get();
  std::cin.sync();

  std::cout << "Please, enter another word: ";
  second = std::cin.get();

  std::cout << "The first word began by " << first << '\n';
  std::cout << "The second word began by " << second << '\n';

  return 0;
}
输出:
         Please, enter a word: test
         Please enter another word: text
         The first word began by t
         The second word began by t


1.11. 输入输出串流类(stringstream)

         stringstream从iostream类继承,但是接口实现上同istringstream和ostringstream一致。


1.12. 输入输出文件流类(fstream)

         在标准库中,fstream从iostream类继承,但是接口实现上同ifstream和ofstream。采用从ifstream和ofstream多继承的方案,个人觉得实现也可以。


1.13. 流缓冲区(streambuf)

         streambuf类是所有流缓冲类的基类,内部处理窄字符(narror char)。
         缓冲区类负责关联流类的读写操作。也就说,流把所有的读写操作都委托给了缓冲区类。缓冲区类是介于流和可控的输入输出序列之间的中介。所有的流对象,不管是有缓冲的还是没有缓冲的,都关联了一个流缓冲对象。当然在流缓冲对象内部可能存在或者不存在真实的缓冲。


         本地化:
         1. 关联locale对象到缓冲区
locale pubimbue (const locale& loc);

         2. 获取当前使用的locale对象
locale getloc() const;


         缓冲管理和位置信息
         1. 设置缓冲区字符数组
streambuf* pubsetbuf (char* s, streamsize n);

         例子:
// set character buffer (pubsetbuf)
#include <fstream>      // std::fstream

int main () {
  char mybuffer [512];
  std::fstream filestr;
  filestr.rdbuf()->pubsetbuf(mybuffer,512);

  // operations with file stream here.

  return 0;
}


         2. 设置内部位置指针到指定位置(相对于way的偏移)
streampos pubseekoff (streamoff off, ios_base::seekdir way, ios_base::openmode which = ios_base::in | ios_base::out);

         例子:
// get file size using pubseekoff
#include <iostream>     // std::cout, std::streambuf
#include <fstream>      // std::fstream

int main () {
  std::fstream filestr ("test.txt");
  if (filestr) {
    std::streambuf* pbuf = filestr.rdbuf();
    long size = pbuf->pubseekoff(0,filestr.end);
    std::cout << "The file size is " << size << " characters.\n";
    filestr.close();
  }

  return 0;
}


         3. 设置内部位置指针到指定位置(绝对位置)
streampos pubseekpos (streampos pos, ios_base::openmode which = ios_base::in | ios_base::out);

         例子:
// changing position with pubseekpos
#include <iostream>     // std::cout, std::streambuf
#include <fstream>      // std::fstream

int main () {

  std::fstream filestr ("test.txt");
  if (filestr) {
    std::streambuf* pbuf = filestr.rdbuf();
    long size = pbuf->pubseekoff(0,filestr.end);  // get size
    if (size>20) {
      char buffer[11];
      // change position to the 10th character
      pbuf->pubseekpos(10);
      // read 10 characters
      pbuf->sgetn (buffer,10);
      // append null character to string
      buffer[10]=0;
      std::cout << buffer << '\n';
    }
    filestr.close();
  }
  return 0;
}


         4. 同步流缓冲
int pubsync();

         例子:
// pubsync member
#include <iostream>     // std::cout, std::streambuf
#include <fstream>      // std::ofstream

int main () {
  std::ofstream ostr ("test.txt");
  if (ostr) {
    std::streambuf * pbuf = ostr.rdbuf();

    pbuf->sputn ("First sentence\n",15);
    pbuf->pubsync();
    pbuf->sputn ("Second sentence\n",16);

    ostr.close();
  }
  return 0;
}


          输入函数:
         1. 获取可读的字符数目
streamsize in_avail();

         例子:
// get file size using pubseekoff
#include <iostream>     // std::cout, std::streambuf, std::streamsize
#include <fstream>      // std::ifstream

int main () {
  std::ifstream ifs ("test.txt");
  if (ifs.good()) {
    std::streambuf* pbuf = ifs.rdbuf();
    char c; ifs >> c;
    std::streamsize size = pbuf->in_avail();
    std::cout << "first character in file: " << c << '\n';
    std::cout << size << " characters in buffer after it\n";
  }
  ifs.close();

  return 0;
}


         2. 前进输入流的当前位到下一字符,并返回下一个字符
int snextc();

         例子:
// show file content - snextc() example
#include <iostream>     // std::cout, std::streambuf
#include <fstream>      // std::ifstream
#include <cstdio>       // EOF

int main () {
  std::ifstream istr ("test.txt");
  if (istr) {
    std::streambuf * pbuf = istr.rdbuf();
    do {
      char ch = pbuf->sgetc();
      std::cout << ch;
    } while ( pbuf->snextc() != EOF );
    istr.close();
  }
  return 0;
}


         3. 返回输入流的当前位字符,并前进当前位到下一个字符
int sbumpc();

         例子:
// show file content - sbumpc() example
#include <iostream>     // std::cout, std::streambuf
#include <fstream>      // std::ifstream
#include <cstdio>       // EOF


int main () {
  std::ifstream istr ("test.txt");
  if (istr) {
    std::streambuf * pbuf = istr.rdbuf();
    while ( pbuf->sgetc() != EOF )
    {
      char ch = pbuf->sbumpc();
      std::cout << ch;
    }
    istr.close();
  }
  return 0;
}


         4. 返回输入流的当前位字符,不改变位置信息
int sgetc();

         例子:
// show file content - sgetc() example
#include <iostream>     // std::cout, std::streambuf
#include <fstream>      // std::ifstream
#include <cstdio>       // EOF


int main () {
  std::ifstream istr ("test.txt");
  if (istr) {
    std::streambuf * pbuf = istr.rdbuf();
    do {
      char ch = pbuf->sgetc();
      std::cout << ch;
    } while ( pbuf->snextc() != EOF );
    istr.close();
  }
  return 0;
}

         5. 从指定的输入流中获取字符串,并把它们存储到s指向的字符串数组中。当n个字符已读或者输入流结束时,析取操作结束。
streamsize sgetn (char* s, streamsize n);

  例子:
// read a file into buffer - sgetn() example
#include <iostream>     // std::cout, std::streambuf, std::streamsize
#include <fstream>      // std::ifstream

int main () {
  char* contents;
  std::ifstream istr ("test.txt");

  if (istr) {
    std::streambuf * pbuf = istr.rdbuf();
    std::streamsize size = pbuf->pubseekoff(0,istr.end);
    pbuf->pubseekoff(0,istr.beg);       // rewind
    contents = new char [size];
    pbuf->sgetn (contents,size);
    istr.close();
    std::cout.write (contents,size);
  }
  return 0;
}


         6. 回退输入流的位置到指定字符c的上一个位置
int sputbackc (char c);
         例子:
// sputbackc example
#include <iostream>     // std::cin, std::cout, std::streambuf, std::streamsize
#include <cstdio>       // EOF

int main () {
  char ch;
  std::streambuf * pbuf = std::cin.rdbuf();

  std::cout << "Please, enter some letters and then a number: ";
  do {
    ch = pbuf->sbumpc();

    if ( (ch>='0') && (ch <='9') )
    {
      pbuf->sputbackc (ch);
      long n;
      std::cin >> n;
      std::cout << "You entered number " << n << '\n';
      break;
    }
  } while ( ch != EOF );

  return 0;
}


         7. 回退输入流的位置到上一个位置,和sputbackc类似,但是不含参数c
int sungetc();

         例子:
// sputbackc example
#include <iostream>     // std::cin, std::cout, std::streambuf, std::streamsize
#include <cstdio>       // EOF

int main () {
  char ch;
  std::streambuf * pbuf = std::cin.rdbuf();

  std::cout << "Please, enter some letters and then a number: ";
  do {
    ch = pbuf->sbumpc();

    if ( (ch>='0') && (ch <='9') )
    {
      pbuf->sputbackc (ch);
      long n;
      std::cin >> n;
      std::cout << "You entered number " << n << '\n';
      break;
    }
  } while ( ch != EOF );

  return 0;
}

         输出函数:
         1. 存储字符于缓冲区当前位置并且移动输入指针位置
int sputc (char c);

         例子:
// typewriter - sputc() example
#include <iostream>     // std::cin, std::cout, std::streambuf
#include <fstream>      // std::ofstream

int main () {
  char ch;
  std::ofstream ostr ("test.txt");
  if (ostr) {
    std::cout << "Writing to file. Type a dot (.) to end.\n";
    std::streambuf * pbuf = ostr.rdbuf();
    do {
      ch = std::cin.get();
      pbuf->sputc(ch);
    } while (ch!='.');
    ostr.close();
  }

  return 0;
}


         2. 存储字符串序列于缓冲区中,直到存储数目到n或者输出序列结束
streamsize sputn (const char* s, streamsize n);

         例子:
// sputn() example
#include <iostream>     // std::streambuf
#include <fstream>      // std::ofstream

int main () {
  const char sentence[]= "Sample sentence";

  std::ofstream ostr ("test.txt");
  if (ostr) {
    std::streambuf * pbuf = ostr.rdbuf();
    pbuf->sputn (sentence,sizeof(sentence)-1);
    ostr.close();
  }

  return 0;
}


1.14. 文件缓冲区流(filebuf)


         成员函数:

         1. 打开文件,并关联其内容到指定的文件缓冲
filebuf* open (const char* filename,  ios_base::openmode mode);

         例子:
// filebuf::open()
#include <iostream>
#include <fstream>

int main () {
  std::ifstream is;
  std::filebuf * fb = is.rdbuf();

  fb->open ("test.txt",std::ios::out|std::ios::app);

  // >> appending operations here <<

  fb->close();

  return 0;
}


         2. 判断缓冲区是否已经关联文件
bool is_open() const;

         例子:
// filebuf::is_open() example
#include <iostream>
#include <fstream>

int main () {
  std::ifstream is;
  std::filebuf * fb = is.rdbuf();
  fb->open ("test.txt",std::ios::in);

  if ( fb->is_open() )
    std::cout << "the file is open.\n";
  else
    std::cout << "the file is not open.\n";

  fb->close();

  return 0;
}


         3. 关闭缓冲区关联的文件,并解除关联
filebuf* close();

         例子:
// filebuf::close()
#include <iostream>
#include <fstream>

int main () {
  std::ifstream is;
  std::filebuf * fb = is.rdbuf();

  fb->open ("test.txt",std::ios::in);

  // appending operations

  fb->close();

  return 0;
}


1.15. 字符串的缓冲流类(stringbuf)


         1. 获取设置字符串内容
string str() const;
void str (const string& str);

         例子:
// stringbuf example
#include <string>       // std::string
#include <iostream>     // std::cout, std::ostream, std::hex
#include <sstream>      // std::stringbuf

int main ()
{
  std::stringbuf buffer;             // empty buffer

  std::ostream os (&buffer);      // associate stream buffer to stream

  // mixing output to buffer with inserting to associated stream:
  buffer.sputn ("255 in hexadecimal: ",20);
  os << std::hex << 255;

  std::cout << buffer.str();

  return 0;
}

输出:

         255 in hexadecimal: ff


1.16 标准库流总结

         上面啰里啰唆的讲了半天,总结如下:

         1. ios_base封装了流的格式

         2. basic_ios封装了流的状态信息。并定义了指向streambuf的指针,也就是说:所有的流都关联一个缓冲区。在流构造时,必须显式的指定一个缓冲区streambuf的指针。文件流和字符串流在构造函数里,并没有看到streambuf指针参数,并不代表不需要,在其内部封装。所有流的输入输出操作都委托给了其内部的streambuf进行

         3. istream定义了输入操作,其中最重要的是重载了">>"操作符。

         4. ostream定义了输出操作,其中最重要的是重载了"<<"操作符。

         5. iostream多重继承于istream和ostream,能够同时完成读写功能。

         6. ofstream、ifstream、fstream完成文件读写工作,定义了文件open,close接口。

         7. ostringstream、istringstream、stringstream完成了对字符串的读写工作,定义了str接口。重载了"<<",">>"操作。

         8. cerr(无缓冲标准错误)、clog(缓冲标准错误)、cout(缓冲标准输出)、cin(行缓冲)为标准库中预定义的stream对象。它们也关联有缓冲对象,其缓冲特性如下:

             cerr(无缓冲标准错误)       -----      没有缓冲,发送给它的内容立即被输出

             clog(缓冲标准错误)          -----      有缓冲,缓冲区满时输出

             cout(缓冲标准输出)          -----      标准输出

             cin(行缓冲)


附录:

在查阅C++流的相关资料时,发现有一篇文章很有意思,重点在底下的讨论。  文章链接为《C++的流设计很糟糕》。



(版权所有,转载时请注明作者和出处  http://blog.csdn.net/arau_sh/article/details/8698456)

你可能感兴趣的:(POCO C++库学习和分析 -- 流 (一))