例如,下面程序用函数get()和put()读写二进制文件。该程序定义一个命令,在DOS下调用该命令可以实现将文件1的内容拷贝到文件2中,相当于DOS命令中的copy命令。
[cpp]
#include<fstream>
#include<iostream>
using namespace std;
int main(int arg,char *argv[])
{
char ch;
if(arg!=3)
{
cout《“命令行输入错误!”《endl;
return 1;
}
ifstream fin(argv );//定义输入流对象,打开第二个参数中的文件
if(!fin)
{
cout《“不能打开源文件”《endl;
return 1;
}
ofstream fout(argv );
if(!fout)
{
cout《“不能打开目标文件”《endl;
return 1;
}
while(fin)//循环写入
{
fin.get(ch);//从源文件中读出字符
fout.put(ch);//写入到目标文件
}
fin.close();
fout.close();
system(“pause”);
return 0;
}
在DOS界面下输入:XX.exe test1.txt test2.txt就能找test1.txt中的内容复制到test2.txt中。前提是test1.txt文件存在,test2.txt如果不存在会自动创建。
3.2.2使用函数read()和write()读写二进制文件
除了上述内容中讲解的使用函数get()和put()读写二进制文件外,c++还支持使用函数read()和write()读写二进制文件。
read()函数是输入流类istream中定义的成员函数,其最常用的原型为:
istream &read(unsigned char *buf,int num);
该函数的作用是从相应的流中读出num个字节或字符的数据,把它们放入指针所指向的缓冲区中。第一个参数buf是一个指向读入数据存放空间的指针,它是读入数据的起始地址;第二个参数num是一个整数值,该值说明要读入数据的字节或字符数。该函数的调用格式为:
read(缓冲区首地址,读入的字节数);
需要注意的是,“缓冲区首地址”的数据类型为“ unsigned char* ”,当输入其他类型数据时,必须进行类型转换。
write()函数是输出流类ostream中定义的成员函数,其最常用的原型为:
ostream &write(const unsigned char *buf,int num);
该函数的作用是从buf所指向的缓冲区把num个字节的数据写到相应的流中。其参数的含义、调用及注意事项与read()相同。
例如:下面程序用函数read()和write()读写二进制文件,实现向文件test.txt写入一个双精度数据类型的数值和一个字符串,并将该文件中的内容读取出显示到屏幕中。
[cpp]
#include<fstream>
#include<string.h>
#include<iostream>
using namespace std;
int main()
{
ofstream outf(“test.txt”);
if (!outf)
{
cout《“不能打开输出文件”《endl;
return 1;
}
double n=123.4;
char str[]=“向文件写入双精度数和字符串”;//13个中文,每个中文占2字节。相当于26个字节,也相当于26个char.
outf.write((char *)&n,sizeof(double));
outf.write(str,strlen(str));
outf.close();
ifstream inf(“test.txt”);
if (!inf)
{
cout《“不能打开输入文件!”《endl;
return 1;
}
inf.read((char *)&n,sizeof(double));//读取文件中的内容
inf.read(str,26);
cout《n《“ ”《str《endl;
inf.close();
system(“pause”);
return 0;
}
文件里显示的内容如下:
3.3 文件的随机读写
随机读写是通过使用输入或输出流中与随机移动文件指针相关的成员函数,通过随机移动文件指针而达到随机访问的。移动文件指针的成员函数主要有 seekg()和seekp(),它们的常用原型为:
istream &seekg(streamoff offset,seek_dir origin);
osream &seekp(streamoff offset,seek_dir origin);
其中,参数origin表示文件指针的起始位置,offset表示相对于这个起始位置的位移量。seek_dir是系统定义的枚举名,origin是枚举变量。origin的取值有以下三种情况。
ios::beg 从文件头开始,把文件指针移动由offset指定的距离。
ios::cur 从文件当前位置开始,把文件指针移动offset指定的距离。
ios::end 从文件尾开始,把文件指针移动由offset指定的距离。
显然,当origin的值为ios::beg时,offset为正;当origin的值为ios::end时,offset的值为负;当origin的值为ios::cur时,offset的值可正可负。offset的值 为正数时从前向后移动文件指针,为负数时从后向前移动文件指针。位移量offset的类型是streamoff,该类型为一个long型数据,它在头文件iostream.h中定义如下:
typedef streamoff long;
此外,移动文件指针的成员函数seekg()和seekp()使用范围和功能为:
函数seekg()用于输入文件,将文件的读指针从origin说明的位置移动offset个字节。
函数seekp()用于输出文件,将文件的写指针从origin说明的位置移动offset个字节。
进行文件随机读写时,可以用下列函数确定文件当前指针的位置:
streampos tellg();
streampos tellp();
其中,streampos是在头文件iostream.h中定义的类型;是long型的;函数tellg()用于输入文件;函数tellp()用于输出文件。
[cpp]
#include<fstream.h>
#include<stdlib.h>
#include<iostream>
using namespace std;
int main(int argc,char *argv[])
{
char ch;
if(3!=argc)
{
cout《“命令行输入错误”《endl;
return 1;
}
ifstream fin(argv );
if (!fin)
{
cout《“不能打开输入文件”《endl;
return 1;
}
fin.seekg(atoi(argv ),ios::beg);//从源文件的头开始读取参数3指定的距离
while(!fin.eof())
{
fin.get(ch);
cout《ch;
}
fin.close();
system(“pause”);
return 0;
}
用dos打开程序后,输入xxx.ext test.txt 5.表示从text.txt的第3个位置开始读取数据。
综合例子:读写不同操作系统中文件,首先创建文件,写入数据后读取并显示在屏幕上。
[cpp]
#include<iostream>
#include<fstream>
#ifdef WIN32
#define TEST_FILE “test.txt”
#else
#define TEST_FILE “/tmp/test.txt” //如果win32路径为“c:\\tmp\\test.txt”
#endif
using namespace std;
int test()
{
{
fstream sfs(“test.txt”,ios_base::out);//文件是写入方式,会覆盖原来的内容
char buf[]=“1234567890”;
sfs.write(buf,sizeof(buf));
sfs.close();
}
{
int len;
char* buf;
fstream sfs(“test.txt”);
sfs.seekg(0,ios::end);//定位到文件末尾
len =sfs.tellg();//返回地址,相当于获取文件的长度
sfs.seekg(0,ios::beg);//获取完之后,将指针提到文件前面
buf = new char[len];
sfs.read(buf,len);//读取文件内容到buf
cout《buf《endl;
delete []buf;
sfs.close();
}
}
int main()
{
test();
system(“pause”);
return 0;
}
例:模拟一个邮件发送端。在DOS命令行下输入XXX.exe mail.txt.相应的信息会写入mail.txt这个文本中。
[cpp]
#include<iostream>
#include<cstdlib>
#include<fstream>
#include<string>
using namespace std;
int main(int argc,char *argv[])
{
assert(argc>1);
ofstream file;
file.open(argv );
if (!file)
{
cout《“打开文件失败”《endl;
system(“pause”);
return 0;
}
int count=0;
file.write((char*)&count,sizeof(int));
string str;
cout《“--请输入收件人邮箱,以-1结束--”《endl;
while(cin》str && str!=“-1”)
{
file《str《' ';
count++;
}
long pos = file.tellp();//获取当前的输出位置
file.seekp(ios_base::beg);//重定位到文件开头
file.write((char*)&count,sizeof(int));//写入收信人信息数目
cout《“--请输入发件人邮箱--”《endl;
file.seekp(pos);//重定位
if (cin》str)
{
file《str《' ';
}
cout《“--请输入主题--”《endl;
if(cin》str)
{
file《str《' ';
}
cout《“--邮件内容以-1结束--”《endl;
while(cin》str && str!=“-1”)
{
file《str《' ';
}
file.close();
system(“pause”);
return 0;
}
例:模拟一个邮件读取端。读取邮件显示的屏幕。
[cpp]
#include<cstdlib>
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
int main(int argc,char* argv[])
{
assert( argc > 1);
ifstream file;
file.open(argv );
if (!file)
{
cout《“打开文件失败”《endl;
system(“pause”);
return 0;
}
string str;
int count = 0;
file.read((char*)&count,sizeof(int));//读取收件人信箱个数
cout《“--收件人信箱--”《endl;
for( int i=0;i<count;i++)
{
file》str;
cout《str《endl;
}
cout《“--发件人信箱--”《endl;
file》str;
cout《str《endl;
cout《“--主题--”《endl;
file》str;
cout《str《endl;
cout《“--内容--”《endl;
while (file》str)
{
cout《str《endl;
}
file.close();
system(“pause”);
return 0;
}