继承图
一个简单的流处理的例子。
基本的函数:
in.get(buffer, SIZE) 读取文件中的一行到buffer中,如果这一行字符的长度大于buffer的size, 他会先读满buffer->处理,然后继续读取,一直读到'/n' 字符。
程序中使用 in.get(); 来读取'/n',并且把'/n'跳过去,如果不使用它的话,在while (in.get(buffer, SIZE))中下次还会读取 '/n'while 循环跳出,只读了文件的第一行。
Sample 1
#include <fstream>
#include <iostream>
using namespace std;
void main()
{
const int SIZE = 100;
char buffer[SIZE];
int i = 0;
{
ifstream in("log.txt");
ofstream out("logout1.txt");
// if the string length is larger then the buffer SIZE
// it will read the max size of buffer and read again until meet '/n'
while (in.get(buffer, SIZE))
{
in.get(); // in.get(buffer, SIZE) meet '/n' will return, so here must read a char and throw the character '/n' then
// while loop can continue or the program will just read the first line.
cout << buffer << endl;
out << i++ << " : " <<buffer << endl;
}
} // here in and out stream will be closed and released
{
ifstream in("logout1.txt");
while (in.get(buffer, SIZE))
{
char* pchar = buffer;
while (*pchar != ':')
pchar++;
*pchar = '-';
in.get();
cout << buffer << endl;
out << buffer << endl;
}
}
cin >> i;
}
打开模式
ios::in 打开输入文件,以这种方式用于ostream打开,使得现存文件不被截断,相当于把文件从头开始重新写入,但保留原来文件中没有被重写的部分。ios::out 打开输出文件,以这种方式用于ostream 打开一个仅用于追加的文件,且未使用ios::in, ios::app, ios::ate时等同于使用ios::trunc。相当于如果文件存在,把文件中原有的内容清空,并且重新写入新的内容。
ios::app 打开一个仅用于追加的文件。
ios::ate 打开一个已存在的文件(输入或输出),并把指针指向文件末尾。
ios::trunc 如果文件存在则截断旧文件
ios::binary 以二进制方式打开文件
这些打开方式当然可以结合使用: out.open("Hello.txt", ios::in|ios::out|ios::binary)
测试用 log.txt 文件
abb
ccc
dddd
eeeee
ffffff
ggggggg
hhhhhhhh
ios::in 的一个例子
在这个例子中 logout2.txt 被写了两次,可以从测试结果中发现这种打开模式的作用。#include <fstream>
#include <iostream>
using namespace std;
void main()
{
const int SIZE = 100;
char buffer[SIZE];
int i = 0;
{
ifstream in("log.txt");
ofstream out("logout1.txt");
ofstream out2("logout2.txt");
// if the string length is larger then the buffer SIZE
// it will read the max size of buffer and read again until meet '/n'
while (in.get(buffer, SIZE))
{
in.get(); // in.get(buffer, SIZE) meet '/n' will return, so here must read a char and throw the character '/n' then
// while loop can continue or the program will just read the first line.
cout << buffer << endl;
out << i++ << " : " <<buffer << endl;
out2 << i++ << " : " <<buffer << endl;
out2 << i++ << " : " <<buffer << endl;
}
} // here in and out stream will be closed and released
{
ifstream in("logout1.txt");
ofstream out("logout2.txt", ios::in);
while (in.get(buffer, SIZE))
{
char* pchar = buffer;
while (*pchar != ':')
pchar++;
*pchar = '-';
in.get();
cout << buffer << endl;
out << buffer << endl;
}
}
cin >> i;
}
ios::in 测试结果:
logout1.txt 的测试结果
0 : a
3 : bb
6 : ccc
9 : dddd
12 : eeeee
15 : ffffff
18 : ggggggg
21 : hhhhhhhh
logout2.txt第一次写入:
1 : a
2 : a
4 : bb
5 : bb
7 : ccc
8 : ccc
10 : dddd
11 : dddd
13 : eeeee
14 : eeeee
16 : ffffff
17 : ffffff
19 : ggggggg
20 : ggggggg
22 : hhhhhhhh
23 : hhhhhhhh
logout2.txt第二次写入:红色部分其实为上次写入的部分。
0 - a
3 - bb
6 - ccc
9 - dddd
12 - eeeee
15 - ffffff
18 - ggggggg
21 - hhhhhhhh
eeee
16 : ffffff
17 : ffffff
19 : ggggggg
20 : ggggggg
22 : hhhhhhhh
23 : hhhhhhhh
使用 ios::out / ios::trunc 的测试结果:
可以看到logout2.txt 中原有的内容被全部清空,并重新写入。
logout1.txt 的测试结果
0 : a
3 : bb
6 : ccc
9 : dddd
12 : eeeee
15 : ffffff
18 : ggggggg
21 : hhhhhhhh
logout2.txt第一次写入:
1 : a
2 : a
4 : bb
5 : bb
7 : ccc
8 : ccc
10 : dddd
11 : dddd
13 : eeeee
14 : eeeee
16 : ffffff
17 : ffffff
19 : ggggggg
20 : ggggggg
22 : hhhhhhhh
23 : hhhhhhhh
logout2.txt第二次写入:
0 - a
3 - bb
6 - ccc
9 - dddd
12 - eeeee
15 - ffffff
18 - ggggggg
21 - hhhhhhhh
使用 ios::app 只是在文件末尾追加新的内容
logout1.txt 的测试结果
0 : a3 : bb
6 : ccc
9 : dddd
12 : eeeee
15 : ffffff
18 : ggggggg
21 : hhhhhhhh
logout2.txt第一次写入:
1 : a
2 : a
4 : bb
5 : bb
7 : ccc
8 : ccc
10 : dddd
11 : dddd
13 : eeeee
14 : eeeee
16 : ffffff
17 : ffffff
19 : ggggggg
20 : ggggggg
22 : hhhhhhhh
23 : hhhhhhhh
logout2.txt第二次写入:
1 : a
2 : a
4 : bb
5 : bb
7 : ccc
8 : ccc
10 : dddd
11 : dddd
13 : eeeee
14 : eeeee
16 : ffffff
17 : ffffff
19 : ggggggg
20 : ggggggg
22 : hhhhhhhh
23 : hhhhhhhh
0 - a
3 - bb
6 - ccc
9 - dddd
12 - eeeee
15 - ffffff
18 - ggggggg
21 - hhhhhhhh
ios::ate 的测试:
用于instream 比较明显,当第二次使用ate打开文件 logout1.txt时,指针指向了文件的末尾,所以logout2.txt没有任何的输入。在使用outstream时它也会把文件清空,并重新写入。
logout1.txt 的测试结果
0 : a
3 : bb
6 : ccc
9 : dddd
12 : eeeee
15 : ffffff
18 : ggggggg
21 : hhhhhhhh
logout2.txt第一次写入:
1 : a
2 : a
4 : bb
5 : bb
7 : ccc
8 : ccc
10 : dddd
11 : dddd
13 : eeeee
14 : eeeee
16 : ffffff
17 : ffffff
19 : ggggggg
20 : ggggggg
22 : hhhhhhhh
23 : hhhhhhhh
logout2.txt第二次测试结果文件为空。
文件流中的定位
输入输出流中定位用到的函数主要有4个 : tellp() tellg() seekp() seekg()
对于ostream调用 tellp() 获得写指针的位置, seekp() 设置写指针的位置。
对于istream调用 tellg() 获得读指针的位置, seekg() 设置读指针的位置。
代码示例:
#include <fstream>
#include <iostream>
using namespace std;
void main()
{
const int SIZE = 100;
char buffer[SIZE];
int i = 0;
ifstream in("log.txt");
ofstream out("logout1.txt");
in.seekg(0, ios::end);
streampos sp = in.tellg();
cout << "file size = " << sp << endl;
in.seekg(-sp/3, ios::end);
streampos sp2 = in.tellg();
cout << "from file to point sp2: " << sp2 << endl;
cout << "read file from the beginning" << endl;
cout << "============================================" << endl;
in.seekg(0, ios::beg);
cout << in.rdbuf() << endl << endl;
// copy to output file
in.seekg(0, ios::beg);
out << in.rdbuf() << endl << endl;
cout << "read file from a set position" << endl;
cout << "============================================" << endl;
in.seekg(sp2);
cout << in.rdbuf() << endl << endl;
streampos outsp1 = out.tellp();
cout << "in output stream where is the position : " << outsp1 << endl;
out.seekp(-outsp1/2, ios::end);
in.seekg(sp2);
out << in.rdbuf() << endl << endl;
cin>> i;
}
测试结果:
output.txt 第一次复制 log.txt 文件的结果
a
bb
ccc
dddd
eeeee
ffffff
ggggggg
hhhhhhhh
第二次插入式写入的结果
a
bb
ccc
dddd
eeeee
ff gggggg
hhhhhhhh
hhh
可以看出,
ggggggg
hhhhhhhh
被插入在指定,并且刷新了原来的文件。