每种输入输出流多有一个概念,“下一个”字符来自哪里(若是输入流)或去哪里(若是输出流)。在某些情况下,可以需要移动这个流的位置,可以用两种方法处理:第一种方式是在流里绝对定位,叫流定位。第二种方式像标准C库函数fseek()函数那样做,从文件的开始,结尾或者当前位置移动给定数目的字节。
流定位(streampos)方法要求先调用"tell"函数:对一个输出流用tellp()函数,对一个输入流用tellg()函数。(“P”指“放指针”,“g”指“取指针”)。要返回到流中的那个位置时,这个函数返回一个streampos,我们以后可以在用于输出流的seekp()函数或用于输入流的seekg()函数的单参数版本里使用这个streampos。
另一种方法是相对查找,使用seekp()和seekg()的重载版本,第一个参数是要移动的字节数,它可以是正的或者负的。第二个参数是查找方向:
ios::beg 从流的开始位置
ios::cur 从流的当前位置
ios::end 从流的末尾位置
#include <fstream>
#include <iostream>
#include <assert.h>
using namespace std;
int main(int argc,char * argv[])
{
assert(argc == 2);
ifstream in(argv[1]);
assert(in);
in.seekg(0,ios::end); //查找整个文件的长度
streampos sp = in.tellg(); //sp为定位指针
cout<<"file size "<<sp<<endl;
in.seekg(-sp/10,ios::end); //重定位
streampos sp2 = in.tellg(); //当前指针sp2
cout<<"sp2 "<<sp2<<endl;
in.seekg(0,ios::beg); //定位到文件开头
cout<<in.rdbuf(); //输出整个文件的内容
in.seekg(sp2); //重定位到sp2
cout<<endl<<endl<<endl<<in.rdbuf()<<endl;
return 0;
}
最基本的这些函数的使用
对输入流操作:seekg()与tellg()
对输出流操作:seekp()与tellp()
下面以输入流函数为例介绍用法:
seekg()是对输入文件定位,它有两个参数:第一个参数是偏移量,第二个参数是基地址。对于第一个参数,可以是正负数值,正的表示向后偏移,负的表示向前偏移。
而第二个参数可以是:
ios::beg:表示输入流的开始位置
ios::cur:表示输入流的当前位置
ios::end:表示输入流的结束位置
tellg()函数不需要带参数,它返回当前定位指针的位置,也代表着输入流的大小。
假设文件test。txt为以下内容:
hello,my world
name:hehonghua
date:20090902
程序为:
#include <iostream>
#include <fstream>
#include <assert.h>
using namespace std;
int main(){
ifstream in("test.txt");
assert(in);
in.seekg(0,ios::end); //基地址为文件结束处,偏移地址为0,于是指针定位在文件结束处
streampos sp=in.tellg(); //sp为定位指针,因为它在文件结束处,所以也就是文件的大小
cout<<"file size:"<<endl<<sp<<endl;
in.seekg(-sp/3,ios::end); //基地址为文件末,偏移地址为负,于是向前移动sp/3个字节
streampos sp2=in.tellg();
cout<<"from file to point:"<<endl<<sp2<<endl;
in.seekg(0,ios::beg); //基地址为文件头,偏移量为0,于是定位在文件头
cout<<in.rdbuf(); //从头读出文件内容
in.seekg(sp2);
cout<<in.rdbuf()<<endl; //从sp2开始读出文件内容
return 0;
}
则结果输出:
file size:45
from file to point:
30
hello,my world
name:hehonghua
date:20090902
date:20090902
建立一个既能读又能写的文件流对象。
疑问:流和文件是随时同步的吗?
#include <fstream>
#include <iostream>
#include <assert.h>
using namespace std;
int main(void)
{
ifstream in("file2.cpp");
ofstream out("file2.out");
out<< in.rdbuf();
in.close();
out.close();
ifstream in2("file2.out",ios::in|ios::out);
ostream out2("file2.out");
cout<< in2.rdbuf();
out2<<"Where dose this end up?";
out2.seekp(0,ios::beg);
out2<<"And what about this";
in2.seekg(0,ios::beg);
cout<<in2.rdbuf();
return 0;
}