C++文件读写操作
文件的概述
所谓“文件”,一般是指相关数据的集合。计算机中的一批数据是以文件的形式存放在外部介质(如磁盘、光盘和U盘)上的。操作系统是以文件为单位对数据进行管理的,也就是说,如果想找存在外部介质上的数据,必须先按文件名找到所指定的文件,然后再从该文件中读取数据。文件在C++看来是字符流或二进制流,统称为文件流。使用一个文件流的过程是固定的,一般步骤如下:(1)打开一个文件,使磁盘文件和文件流对象建立联系;(2)将数据按文本方式写入一个文件,就如同cout用于向显示器送数据。以后可从这个文件读取数据,就如同cin用于键盘输入;(3)当不再使用文件时,要关闭文件,此时文件将从缓冲区中完全写回磁盘。这样,可以永久保存数据。
文件的分类
外部文件和内部文件
外部文件:指磁盘文件、光盘文件和U盘文件。目前使用最广泛的是磁盘文件,在程序中对光盘文件和U盘文件的使用方法与磁盘文件相同。本章所说的文件都是指磁盘文件。
内部文件:指在程序中运行的文件,更正式的称谓是“文件流对象”。
文本文件和二进制文件
ASCII文件:ASCII文件又称文本(text)文件或字符文件,它的每1字节放一个ASCII代码,代表一个字符。
二进制文件:又称内部格式文件或字节文件,是把内存中的数据按其在内存中的存储形式原样输出到磁盘上存放。
文件流类和文件流对象
在C++的I/O类库中不仅可以看到除了标准输入输出流类istream、ostream和iostream类外,还有3个专门用于文件操作的文件类
(1)ifstream类,它是从istream类派生的,用来支持从磁盘文件的输入。(2)ofstream类,它是从ostream类派生的,用来支持向磁盘文件的输出。(3)fstream类,它是从iostream类派生的,用来支持对磁盘文件的输入输出。在用磁盘文件时,由于情况各异,无法事先统一定义,必须由用户自己定义。此外,对磁盘文件的操作是通过文件流对象(而不是cin和cout)实现的。文件流对象是用文件流类定义的,而不是用istream和ostream类来定义的。
文件的打开和关闭
打开文件
调用成员函数open()的一般形式为:
文件流对象.open(磁盘文件名,输入输出方式)
另一种用的多的形式如下,作用域open()函数相相同。
ofstream outfile("file.txt",ios::out);
关闭文件
outfile.close( ); /*将输出文件流所关联的磁盘文件关闭*/
文件的读写
文本文件的读写
编写程序,向一个文件中写入10个整数。
#include<iostream>
#include<fstream>
using namespace std;
int main()
{
int a[10];
char f[50];
cout<<"请输入文件名:" << endl;
cin >> f;
ofstream outfile(f, ios::out); //参数ios::out可以省略。如果不写此项,则默认为ios::out。
if (!outfile)
{
cout<<"文件无法打开!" << endl;
exit(1); //某些老版本的C++要求包含头文件stdlib.h,而在新版本的C++则不要求包含。
}
cout << "请输入10个整数:" << endl;
for (int i = 0; i < 10; i++)
{
cin >> a[i];
outfile<<a[i] << "";
}
outfile.close();
return 0;
}
编写程序,从一个文件中读出内容
#include<iostream>
#include<fstream>
using namespace std;
int main()
{
int a[10];
char f[100];
cout<<"请输入文件名:" << endl;
cin >> f;
ifstream infile(f, ios::in | ios::_Nocreate); //以读的模式打开文件
if (!infile)
{
cout<<"文件无法打开!" << endl;
exit(1);
}
cout << "读取文件中的内容:" << endl;
for (int i = 0; i < 10; i++)
{
//从磁盘文件读入10个整数存放到a数组中
infile >> a[i]; //不能是cin>>a[i]
cout << a[i] << "" << endl;
}
infile.close();
return 0;
}
编写程序,从键盘读入一行字符,把其中的字母字符依次存放在磁盘文件XXX.txt中,再读出磁盘文件中的字符串。
#include <iostream>
#include<fstream>
using namespace std;
void save_File()
{
cout<<"打开文件" << endl;
ofstream outfile("D:\project\project_C++\XXX.txt");
if (!outfile)
{
cerr << "文件打开错误!" << endl;
exit(1);
}
char c[100];
cout << "请写入字符串:";
cin.getline(c, 100); //从键盘读取一行字符串
for (int i = 0; c[i]!=0; i++) //直到遇到'/0'为止
{
//如果是字母字符串,将字母字符存入磁盘文件
if (c[i] >= 65 && c[i] <= 90 || c[i] >= 97 && c[i] <= 122)
{
outfile.put(c[i]);
}
}
cout << endl;
outfile.close();
}
void get_File()
{
char ch;
cout << "打开文件" << endl;
ifstream infile("D:\project\project_C++\XXX.txt", ios::in | ios::_Nocreate);
if (!infile)
{
cerr << "打开文件错误!" << endl;
exit(1);
}
cout << endl;
infile.close();
}
int main()
{
save_File();
get_File();
return 0;
}
【程序分析】本程序用了文件流的put()、get()和getline()成员函数实现输入和输出,用成员函数getline()从键盘读入一行字符,调用函数的形式是cin.getline(c, 100),从磁盘文件读一个字符时用infile.get(ch)。
随机读写
编写程序,将1~100的奇数存入二进制文件,并读取指定数据。
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
int i, x;
ofstream outfile("..//1024.txt", ios::out | ios::binary);
if (!outfile)
{
cout << "打开错误!";
exit(1);
}
for (i = 1; i < 100;i += 2)
{
outfile.write((char*)&i, sizeof(int)); //写入100以内3的倍数
}
outfile.close();
ifstream infile("..//1024.txt", ios::in | ios::binary);
if (!infile)
{
cout << "打开错误!";
exit(1);
}
for (i = 1; i < 4 && !infile.eof(); i++)
{
infile.read((char*)& x, sizeof(int));
cout << x << '\t';
}
infile.close();
return 0;
}
C++对字符串流的读写
编写程序,将一组数据保存在字符数组中。
#include <iostream>
#include <strstream>
using namespace std;
struct student
{
char name[20];
int age;
char sex;
};
int main()
{
student stu[3] = { "zhang song wen",19,'M', "zhang yi",21,'M',"li yi tong",18,'W' };
char S[50];
ostrstream strout(S, 80);
for (int i = 0; i < 3; i++)
{
strout << stu[i].name << "\t" << stu[i].age <<"\t" << stu[i].sex << endl;
}
strout << ends; //ends是C++de I/O操作符,插入一个‘\\0’
cout << "array c:\n" << S << endl; //显示字符串数组c中的字符
return 0;
}
综合应用
编写程序,学校要输入5位学生的信息,结果第3位学生的信息录入错误,需要进行修改。
程序思路:
①把他们的信息存到磁盘文件中;
②将磁盘文件中的第1个、第3个和第5个学生数据读入程序,并显示出来;
③将第3个学生的数据修改后存回磁盘文件中的原有位置;
④从磁盘文件读入修改后的5个学生的数据并显示出来。
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
struct student
{
int num;
char name[20];
float score;
};
int main()
{
student stud[5] = {
1001,"张",98,
1002,"王",86.6,
1004,"曾",99,
1006,"江",85,
1010,"刘",92.2,
};
//用fstream类定义输入输出二进制文件流对象iofile
fstream iofile("d:\\1024.txt", ios::in | ios::out | ios::binary);
if (!iofile)
{
cerr<<"open error!" << endl;
abort();
}
for (int i = 0; i < 5; i++)
{
iofile.write((char*)&stud[i], sizeof(stud[i]));
}
student stud1[5]; //用来存放从磁盘文件读入的数据
for (int i = 0; i < 5; i=i+2)
{
//定位第1,3,5学生数据
iofile.seekg(i * sizeof(stud[i]), ios::beg);
//先后读入3个学生数据,存放在stud1[0],stud1[1],stud1[2]中
iofile.read((char*)&stud1[i / 2], sizeof(stud1[0]));
//输出stud1[0],stud1[1],stud1[2]各成员的值
cout << "第" << i + 1 << "个学生:" << stud1[i / 2].num << "" << stud1[i / 2].name<< "" << stud1[i / 2].score << endl;
}
cout << endl;
stud[2].num = 1012; //修改第3个学生的学号
strcpy_s(stud[2].name, "李"); //修改第3个学生的姓名
stud[2].score = 80; //修改第3个学生的成绩
iofile.seekp(2 * sizeof(stud[0]), ios::beg); //定位于第1个学生数据的开头
iofile.write((char*)&stud[2], sizeof(stud[2])); //更新第3个学生数据
iofile.seekg(0, ios::beg); //重新定位于文件开头
for (int i = 0; i < 5; i++)
{
iofile.read((char*)&stud[i], sizeof(stud[i])); //读入5个学生的数据
cout << "第" << i + 1 << "个学生:" << stud[i].num << "" << stud[i].name << "" << stud[i].score << endl;
}
iofile.close();
return 0;
}