目录
学习完文件,我感觉文件在程序设计中占据核心地位。所以今天来谈一谈如何写好c++文件:
无论是人们写的文章还是生活的片段,总希望能够永久的保存下来。同样,我们编写的程序也希望能够以文件的形式保存下来,这样能够减少很多不必要的麻烦。
c++是c的延续,因此在文件部分上c++与c有很多相似之处,只是函数名与开关文件的方式有不同而已。
文件的作用:
1.当有大量数据输入时,可以通过编辑工作,事先建立输入数据文件,程序运行时从指定文件读入数据,从而实现数据一次输入多次使用的目的。
2.当有大量数据输出时,也可以将其输出到指定的文件,这样可以随时查看数据的任何部分。
(一):c++文件流
(1)文件流的分类
1. ifstream:由istream派生而来,提供读文件的功能。文件流对象默认打开方式是in。
2. ofstream:由ostream派生而来,提供写文件的功能。文件流对象默认打开方式是out。另外,要注意的是:按照out方式打开文件,会清空文件内容,因此,可以指定打开方式为app追加到末尾。
3. fstream:由iostream派生而来,提供读写同一个文件的功能。文件流对象默认打开方式是in和out
(2)文件流对象的创建
先假设infile 和outfile为文件流对象,要用它们来操作文件“in”和文件“out”。
方式一:在定义文件流对象的同时打开文件,具体如下:
ofstream outfile("out");//打开out文件
方式二:拆分来写:先定义文件流对象,然后调用open函数打开文件:
ofstream outfile;
ifstream infile;
infile.open("in");//打开in文件
outfile.open("out");//打开out文件
(3)文件流对象的关闭
在程序设计中,如果只打开文件而不关闭它,会造成资源的占用和浪费,所以要及时关闭文件。
关闭方式:
infile.close();//关闭文件
outfile.close();
(4)检查文件打开
一般情况下,由于不确定是否正确打开了某一个文件,常常需要写一段检查代码:
if (!infile)
{
cerr << "unable open it" << infile << endl;
return -1;
}
值得一提的是:cerr是“错误输出流”,它与cout的差别在于cerr不能重定向,且不缓冲。
(二)c++文件流的读写
(1)顺序读写
顺序读入时,先读入文件前面的数据,再读入文件后面的数据,这称为顺序读入;先写入的数据存放在文件前面的位置,后写入的数据存放在文件后面的位置,这称为顺序写入。
(2)顺序读写的相关函数
1. get()函数与put()函数:
类似于c语言中的fgetc()和fputc()函数
利用get()函数可以从文件中读取一个字符,put()函数可以向文件中写入一个字符。
infile.get(c);//从文件读取一个字符
outfile put(c);//向文件输入一个字符
2. getline(char * ,int)函数:
利用getline()函数可以从文件中读取一行文本,最多n个字符,传入到字符数组中去。参数表中第一个参数代表字符串数组,第二个参数代表传入的字符的个数。
char buff[10];
ifstream in("e:\\file1.txt");
ofstream out("e:\\file2.txt");
while (in.getline(buff, 10))
{
out << buff << endl;
}
in.close();
out.close();
3. 提取运算符>>和插入运算符<< :
c++中文件的读写也可以用提取运算符和插入运算符来完成。这时将文件流对象当成键盘或显示器。
int a = 1;
infile >> a;
outfile << a;
4. read()和write()函数:
read()和write()函数作用是以二进制方式读写文件。
write被ofstream所继承,是ostream的一个成员函数。
read被ifstream所继承,是istream的一个成员函数。
原型:read(char *buffer,streamsize size);
write(char *buffer, streamsize size);
此函数与c语言的fwrite()和fread()函数很相似,参数表也很相似。第一个参数buffer代表一块地址,用来存放读入或者写出的数据。第二个参数size代表从缓存区中读出或者写入的数据的字节数。
struct Student
{
}student;
fout.write((char*)&studnet, sizeof(Student);//以二进制方式写文件
(3)随机读写
为什么要使用随机读写?
在文件中有一个隐藏的文件“读写位置指针“。在顺序读写时,每读写一个数据,读写位置指针就会往后移一次,直到数据项末尾。
而事实上,在程序设计时,常常因为要考虑用户的需求,即读取指定位置数据,因此采用随机读写,随机读写的精髓就是移动“文件位置指针”。
(4)随机读写的常用函数
1. 1 seekg()和seekp()函数
这两个函数类似于c语言中的fseek()函数。seekg()是对输入文件进行定位的函数,seekp()是对输出文件进行定位的函数。它们各自含有两个参数,第一个参数代表偏移量,第二个参数代表起始地址。
1.2 代码偏移量可正可负,正数代表后移,负数代表前移。
0或者ios::beg:表示输入文件流的开始位置;
1或者ios::cur:表示输入文件流的当前位置;
2或者ios::end:表示输入文件流的末尾 。 具体如下:
fin.seekg(0, ios::end);
long offset = fin.tellg();
fin.seekg(offset - sizeof(AddressRecord), ios::beg);
fin.read((char*)&record, sizeof(AddressRecord));
cout << record.no << '\t' << record.name << '\t' << record.phone << endl;
fin.seekg(0, ios::beg);
fin.read((char*)&record, sizeof(AddressRecord));
cout << record.no << '\t' << record.name << '\t' << record.phone << endl;
fin.seekg(0, ios::cur);
fin.read((char*)&record, sizeof(AddressRecord));
cout << record.no << '\t' << record.name << '\t' << record.phone << endl;
fin.close();
2. tellg()和tell()函数
这两个函数类似于c语言中的ftell()函数,返回输入文件和输出文件的当前位置。函数没有参数,返回值为输入文件和输出文件的当前位置。
3. eof()函数
这个函数的作用是判断当前文件读写位置指针是否到了end(结尾)位置,若返回true,则说明到末尾了,否则没到末尾。
(三)文件缓冲区
(1)什么是文件缓冲区:
说到文件,再来说一下文件缓冲区吧:
1. 缓冲区又称为缓存,它是内存空间的一部分。也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区。
缓冲区根据其对应的是输入设备还是输出设备,可以分为输入缓冲区和输出缓冲区。
2. 那么为什么要引入缓冲区呢?
比如我们从磁盘里取信息,我们先把读出的数据放在缓冲区,计算机再直接从缓冲区中取数据,等缓冲区的数据取完后再去磁盘中读取,这样就可以减少磁盘的读写次数,再加上计算机对缓冲区的操作大大快于对磁盘的操作,所以应用缓冲区可大大提高计算机的运行速度。
3. 从内存向磁盘输出数据必须先送到内存缓冲区,等缓冲区装满后,才把数据一起送到磁盘;同样,如果从磁盘向内存读入数据,则一次从磁盘文件将一批数据读入到内存缓冲区,然后再逐个将数据送到程序数据区。
(2)清空文件缓存区
如果待写入的数据存储在缓冲区中,而又要立即将缓冲区的数据写入文件,可使用
fflush()函数实现。该函数的一般形式是 fflush(缓冲区指针)。
清空缓存区函数:
1. fflush(stdin) 刷新标准输入缓冲区
2. fflush(stdout) 刷新标准输出缓冲区
3. whlie((ch=getchar())!='\n&&ch!=EOF)
{
;
}
(四)代码展示
//添加3个学号为1,2,3的学生成绩,并将成绩信息顺序存入data.dat文件中,然后按照3,1,2的顺序读出并显示到屏幕上
#include<iostream>
#include<fstream>
#include<cstdlib>
using namespace std;
const int maxlenofname = 12;
const int lenofphone = 12;
typedef struct AddressRecord
{
int no;
char name[maxlenofname];
char phone[lenofphone];
}AddressRecord;
int main()
{
AddressRecord record;//结构体变量
//以二进制方式建立文件流写文件
fstream fout("Record.dat", ios::binary | ios::out);
cout << "请输入联系人信息:" << endl;
while (true)
{
cin >> record.no;
if (record.no <= 0)
{
break;
}
cin >> record.name;
getchar();
cin >> record.phone;
fout.write((char*)&record, sizeof(AddressRecord));
}
fout.close();
int num = 0;
//以二进制方式建立文件流读文件
fstream fin("Record.dat", ios::binary | ios::in | ios::out);
if (!fin)
{
cerr << "open this file error!" << endl;
exit(0);
}
fin.seekg(0, ios::end);
long offset = fin.tellg();
fin.seekg(offset - sizeof(AddressRecord), ios::beg);
fin.read((char*)&record, sizeof(AddressRecord));
cout << record.no << '\t' << record.name << '\t' << record.phone << endl;
fin.seekg(0, ios::beg);
fin.read((char*)&record, sizeof(AddressRecord));
cout << record.no << '\t' << record.name << '\t' << record.phone << endl;
fin.seekg(0, ios::cur);
fin.read((char*)&record, sizeof(AddressRecord));
cout << record.no << '\t' << record.name << '\t' << record.phone << endl;
fin.close();
return 0;
}
以上就是我对c++文件部分的理解,不足之处还望提示。