您的位置:首页 > 编程语言 > C语言/C++

文件的读写操作3

2015-06-10 18:14 465 查看
最后,将为大家介绍文件的随机存取。文件的随机存取是指按照要求直接,而不是依次,移动到文件的任何位置。要实现文件的定位,C++提供了seekg和seekp两个函数。前者将输入指针定位到指定的文件位置,而后者将输出指针定位到制定的文件位置。实际上,由于fstream类使用的是缓冲区来存储中间数据,因此,指针指向的其实是缓冲区中的位置,而不是实际的文件位置。这两个函数都有如下的两个原型:

istream & seekg/seekp(streampos);//移动输入/输出指针到距离文件开头相应位置
istream & seekg/seekp(streamoff,ios_base::seek_dir);//移动输入/输出指针到距离文件指定位置的相应位置


前者将相应指针定位到距离(以字节为单位)文件开头的相应位置。后者将文件定位到距离(以字节为单位)指定文件位置的相应位置。说是指定文件位置,其实seek_dir只有三个值:ios_base::beg,ios_base::cur,ios_base::end分别对应文件开头、当前和结尾位置。streamoff为相对于相应位置的偏移量。下面列出了seekg函数的几个例子,seekp函数也与之类似,其中fin为ifstream对象。

fin.seekg(5,ios_base::beg);//离文件开始5个字节距离位置
fin.seekg(-2,ios_base::cur);//离当前位置向前2个字节距离位置
fin.seekg(0,ios_base::end);//离文件结尾0个字节距离位置,即文件结尾
fin.seekg(521);//离文件开始521个字节距离位置


为了给大家介绍些新东西,下文的例子中,特意使用了fstream对象,此对象继承了iostream类以及两个缓冲区,即输入和输出缓冲区,并能同步化这两个缓冲区的处理,使输入指针和输出指针能够在相应的缓冲区中协调的移动。

#include <iostream>
#include <fstream>
using namespace std;

struct testStruct
{
char name[20];
double scores;
};

inline void eatline(){while(cin.get()!='\n') continue;}//get rid of newline

int main()
{
const char* fileName = "1.txt";
testStruct t;
fstream finout(fileName,ios_base::in|ios_base::out|ios_base::binary);//二进制读写模式
if (!finout.is_open())
{
cout<<"file open error!"<<endl;
exit(EXIT_FAILURE);
}
for (int i=0;i<3;i++)
{
cin.get(t.name,20);
cin>>t.scores;
eatline();//去掉换行符,否则换行符会一直保留在缓冲区中,使两个数据无法输入
finout.write((char*)&t,sizeof(t));//写入文件
}

finout.seekg(0);//将输入指针移动到文件头。其实不是必须的,只是为了说明如何使用seekg。
while (finout.read((char*)&t,sizeof(t)))//未到文件尾,读取文件
{
cout<<t.name<<": "<<t.scores<<endl;
}
if (finout.eof())//到达文件尾后,程序将设置eofbit元素,使用clear重置流状态,使程序可以再次访问程序
finout.clear();

int n;
cout<<"Enter the number you wish to change: "<<endl;
cin>>n;
eatline();//去掉换行符
streampos pos = (n-1) * sizeof(t);//使其从1开始计数
finout.seekp(pos);//将输出指针移动到指定位置
finout.read((char*)&t,sizeof(t));//读取当前位置内容
finout.clear();//清空缓冲区
cout<<"Your selection: "<<endl;
cout<<t.name<<": "<<t.scores<<endl;

cout<<"Enter the testStruct data: "<<endl;
cin.get(t.name,20);
eatline();//去掉换行符
cin>>t.scores;
eatline();//去掉换行符
finout.seekp(pos);//将输出指针移动到指定位置
finout.write((char*)&t,sizeof(t));//写入

finout.seekg(0);//将输入指针移动到文件起始位置
while (finout.read((char*)&t,sizeof(t)))//未到文件尾
{
cout<<t.name<<": "<<t.scores<<endl;
}
return 0;
}


运行结果如下:



存入的二进制文件如下:



说明:关于程序上面的注释中已有详细说明,在此不再赘述。大家要注意以下两点:
1、cin和get会将换行符留在缓冲区,要注意其对下文输入的影响。
2、当程序读取并显示整个文件后,将会对eofbit进行设置,程序将会禁止对文件做进一步的读写。应使用clear重置流状态,使程序可以在此访问该文件。
本人才疏学浅,若有错误,欢迎指正,不胜感激。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息