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++的 输入输出类图:
下面对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 // 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 // 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 // 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 // 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 // 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 // std::cout
#include // 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
locale getloc() const;
1.2 basic_ios
basic_ios定义出“与字符类型及其相应字符特性相关”的stream class的共同属性,其中包括清除流状态、设置流状态、拷贝流标志、返回或设置流缓冲区指针、设置本地化相关信息、返回或设置填充字符、字符转换,还包括了stream所用的缓冲器.basic_ios在其内部定义了一个指向streambuf的指针。
template
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 // std::cout, std::ios
#include // 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
bool operator!() const;
如果没有错误标记被设置(failbit或badbit),返回true,否则返回false
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 // std::cout
#include // 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);
}
basic_ios& copyfmt (const basic_ios& rhs);
例子:
// copying formatting information
#include // std::cout
#include // 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;
}
char_type fill() const;
char_type fill (char_type fillch);
例子:
// using the fill character
#include // 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
iostate exceptions() const;
void exceptions (iostate except);
例子:
// basic_ios::exceptions
#include // std::cerr
#include // 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* tie() const;
basic_ostream* tie (basic_ostream* tiestr);
例子:
// redefine tied object
#include // std::ostream, std::cout, std::cin
#include // 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* rdbuf() const;
basic_streambuf* rdbuf (basic_streambuf* sb);
例子:
// redirecting cout's output thrrough its stream buffer
#include // std::streambuf, std::cout
#include // 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 // std::ios, std::istream, std::cout
#include // 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 // 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 // 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 // std::cin, std::cout
#include // 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 // 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 // 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 // std::cin, std::cout
#include // 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 // std::cout
#include // 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 // std::cin, std::cout
#include // 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 // std::cin, std::cout
#include // 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 // std::cout
#include // 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 // 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 // std::cout, std::ostream, std::ios
#include // 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 // std::cout, std::right, std::endl
#include // 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 // std::cin, std::cout
#include // 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 // 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 // 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
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 // 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 // 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 // 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 // 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 // std::cout
#include // 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 // 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;
}
filebuf* rdbuf() const;
例子:
// copy a file using file stream buffers
#include // std::filebuf, std::ifstream, std::ofstream
#include // 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 // std::cout
#include // 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 // std::cout
#include // 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 // std::cout
#include // 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 // std::cout
#include // 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 // std::cout
#include // 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 // std::cout, std::ios
#include // 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 // std::string
#include // std::cout
#include // 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: 1012. 插入操作符
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 // std::cout, std::right, std::endl
#include // 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 // std::cin, std::cout
#include // 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 // 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 // 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 // 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 // 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 // std::cout
#include // std::istringstream
#include // 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 // std::string
#include // std::cout
#include // 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 // std::string
#include // std::cout
#include // 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(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 // 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 // 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 // std::cin, std::cout
#include // 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 // 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 // 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 // std::cin, std::cout
#include // 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 // std::cout
#include // 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 // std::cin, std::cout
#include // 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 // std::cin, std::cout
#include // 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 // std::cout
#include // 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 // std::cout
#include // 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 // 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 // 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 // std::cout, std::streambuf
#include // 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 // std::cout, std::streambuf
#include // 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 // std::cout, std::streambuf
#include // 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 // std::cout, std::streambuf, std::streamsize
#include // 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 // std::cout, std::streambuf
#include // std::ifstream
#include // 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 // std::cout, std::streambuf
#include // std::ifstream
#include // 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 // std::cout, std::streambuf
#include // std::ifstream
#include // 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 // std::cout, std::streambuf, std::streamsize
#include // 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 // std::cin, std::cout, std::streambuf, std::streamsize
#include // 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 // std::cin, std::cout, std::streambuf, std::streamsize
#include // 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 // std::cin, std::cout, std::streambuf
#include // 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 // std::streambuf
#include // 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
#include
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
#include
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
#include
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 // std::string
#include // std::cout, std::ostream, std::hex
#include // 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: ff1.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(缓冲标准输出) ----- 标准输出
附录:
在查阅C++流的相关资料时,发现有一篇文章很有意思,重点在底下的讨论。 文章链接为《C++的流设计很糟糕》。
(版权所有,转载时请注明作者和出处 http://blog.csdn.net/arau_sh/article/details/8698456)