`
jafisher
  • 浏览: 55501 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

文件流操作之C++版

阅读更多
  昨天简单介绍了一下C中的文件流操作,其实更强大、更复杂的操作还得看C++,毕竟C++是C的加强,不论是从功能还是效率上都比C高出一个档次,而我们在实际的流操作中对C++的使用怕也是更加频繁,所以接下来就重点讲解下C++的文件流操作。

  那么就先说说文件流的定义吧。文件流是以外存文件为输入/输出对象的数据流。输出文件流是从内存流向外存文件的数据,输入文件流是从外存文件流向内存的数据。每一个文件流都有一个内存缓冲区与之对应。

与C一样,C++的文件流操作也分为同样的三个部分。
(1)打开文件
(2)读/写文件
(3)关闭文件

在这之前先说下文件流的类:
(1) ifstream ifile:只输入用,它是从istream 类派生的。
(2) ofstream ofile:只输出用,它是从ostream 类派生的。
(3) fstream iofile:既输入又输出用,它是从iostream 类派生的。
即是说,如果你想要的操作只是从文件中读数据,可这么定义:
ifstream fin("...");

要写入文件,则是:
ofstream fout("...");

如果既有读操作,又是写操作,就可以直接定义:
fstream fin("...");
fstream fout("...");

好了,知道了这些就可以进行文件的打开操作了。
打开文件有两种方式,一种是自动打开,一种是调用open函数打开。
(1)自动打开:
fstream file("filename",iosmode);

(2)使用open函数打开:
fstream file;
file.open("filename",iosmode);

也可以用指针的形式打开:
fstream* file = new fstream;
file->open("filename",iosmode);

可以注意到,这里的iosmode指的是打开文件的方式,和C一样,C++中的文件流操作中的文件也是分成文本文件和二进制文件,不光是文件,打开方式也有几种类型,下面介绍的这些只是我们平时可能会用到的,当然还有很多类型,只是平时很难会用到,所以就不再介绍了。

ios::in               以输入方式打开文件
ios::out              以输出方式打开文件(默认方式)
ios::app              以追加方式打开文件,数据写到文件尾
ios::ate              打开一个存在文件,文件指针指向文件尾
ios::binary           以二进制方式打开文件
ios::in|ios::out      以输入输出方式打开文件
ios::in|ios::binary   以二进制方式打开一个输入文件
ios::out|ios::binary  以二进制方式打开一个输出文件
ios::binary|ios::app  以二进制方式追加打开一个文件

需要注意的是,一般打开文件的默认方式是打开文本文件,所以二进制文件必须显式打开。
另外,在输出的时候也要注意,默认的输出方式是覆盖之前的数据,所以如果要保存之前的数据的话,一定要记得以追加方式输出啊,我之前就是因为这个问题郁闷了很久~!

关闭文件:
这个和C一样,都是调用close()函数,即file.close();

然后就是我们最为关心的流读写操作了,先介绍一下常用的i/o流成员函数。
1.输入:
(1)get():读取一个字符或一个字符串
这个函数我所不理解的是书上说它有三种形式,不带参数,带一个参数和带三个参数,但我自己在用的时候用的都是不带参数和带两个参数的,貌似都可以。
不带参数的get()是从文件中读取一个字符,而且包括空格,然后返回这个字符。

ifstream fin("test.txt",ios:in);
char ch;
while((ch=fin.get())!=EOF)
  cout.put(ch);

这样就能把test中的字符一个一个读取出来输出屏幕上了,不过它每次只能读一个字符。
带一个参数的get(char* ch,int size)就是读取一段固定长度的字符串。

ifstream fin("test.txt",ios::in);
char ch[100];
fin.get(ch,10);
cout<<ch;

这样就能把test中一段长度为10的字符串读取出来并输出到屏幕上,不过它只能读取固定长度的字符串,如果事先不知道文件中有多大的数据,确实会有点不爽啊。

(2)getline():读取一行字符串
这个函数和get()差不多,在我理解看来是有两种用法,不带参数和带两个参数。

ifstream fin("test.txt",ios::in);
char ch1[100],ch2[100];
ch1 = fin.getline();
cout<<ch1<,endl;
fin.getline(ch2,10);
cout<<ch2<<endl;

这样都是把文件中的一行读取出来并显示到屏幕上,它的不足是不能区分一行中出现的不同类型的字符或整数。当然读整数可以用 fin>>num 的方法把文件中的整数直接读到num中。
其实将get()和getline()结合起来使用是一种不错的选择,如文件中的革一行保存的数据是一个学生的学号,姓名和地址。

ifstream fin("test.txt",ios::in);
int num;
char name[10];
char address[20];
fin>>num;
fin.get(name,10);
fin.getline(address,20);

这样,就把一行中的不同信息都保存起来了。

(3)read():从文件中读取特定字符的字节,这种方式特别适合二进制文件的读取。
如果想要把一个对象保存在文件中,并以对象的方式读取信息,那read()方式真的是太合适了。如想要读取文件中一个学生的信息。

ifstream fin("test.txt",ios::binary);
Student s;
fin.read((char*)&s,sizeof(s));

这样,不管文件中保存的数据有多少不同的类型,抑或根本不知道某一数据的长度,通过这种方式都可以把文件中的某一个学生对象信息保存在s对象中了。这里因为s是自定义数据类型,所以要先把它转化成char* 类型。

2.输出:
输出的方法相对来说要少点,因为输出的过程相对也要简单一点。
(1)put():向文件中写入一个字符。

ofstream fout("test.txt",ios::out);
char ch[6]="hello";
int i=0;
whlie(ch[i]!=EOF)
  put(ch[i++]);

这样就可以把字符串 hello 输出到文件中了,不过它只能将字符一个一个输出,很不方便。

(2)write():向文件写入一定数量的字节,与read()一样,这种方式也特别适合二进制文件的输出。尤其是想要把一个对象保存到文件中时。学生类就不在这里写出来了。

ofstream fout("test.txt",ios::binary);
Student s(1,"jack","1000");
fout.write((char*)&s,sizeof(s));

这样就把学生对象s以二进制的方式保存在文件中了。这里有个问题需要注意,如果只是保存一个对象可能这样写,如果是想保存多条对象,就得稍微改改了。
ofstream fout("test.txt",ios::binary|ios::app);

这样才不会覆盖之前的对象。

当然,其实输出流还有一种更简单的形式,就是用fout直接输出。

int num;
char name[10];
char address[20];
cin>>num>>name>>address;
fout<<num<<name<<address;

如此也可以将数据写入文件中,读取时调用get()或是getline()函数就行了。

除了这些以外,C++中还有一种随机文件的读取,它可以从文件的任意位置随机读取数据。
这里面的两个重要函数就是seekg(n)和tellg()。
seekg(n)可以定位到文件的位置n,从这一点读取或写入数据。
tellg()则是返回当文件的指针值。

写了这么多,我想如果遇到文件流操作的问题,这些应该基本足以解决了吧。当然也希望能与大家分享更多的有关文件流的精髓。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics