目录
知识点讲解
文件流:
C++在头文件fsream中定义了C++的文件流类体系,当程序中使用文件时,要包含头文件fstream.h
在涉及文本文件的操作时,将输入文件看成键盘,将输出文件看成显示器,格式不变;
只需要在程序中增加打开与关闭文件的语句。
文本文件的打开与关闭:
在文件操作前,需要将程序与待操作的文件联系起来,使程序可以“引用”文件。
在程序内定义一个文件类的对象,该对象与文件发生联系,
程序内所有与文件的操作都是对该对象的操作。
ifstream(输入流)定义用于输入的文件对象
ofstream(输出流)定义用于输出的文件对象
输入和输出是相对“内存”而言的。
fstream infile,outfile;//两个对象,可以联系两个输入输出文件;
ifstream infile;//对象只能联系输入文件;
ofstream outfile;//对象只能联系输出文件;
如何使文件类的对象与想要操作的文件发生联系?
用对象打开文件:
ifstream infile;//定义输入文件类对象
infile.open("myfile.txt"t);//利用函数打开某一文件
//打开文件“myfile1.txt”用于输入,并将这个文件与输入文件类对象infile建立联系,
//今后用到这个文件“myfile1.txt”的地方就用infile来代替。
打开文件的作用是,使文件流对象与要使用的文件名之间建立联系。
ofstream outfile;//定义输出文件类对象
outfile.open("myfile1.txt");//打开某一文件供输出
用完文件后,使用成员函数关闭文件,如:
ifsream infile;
ofstream outfile;
infile.open("myfile1.txt");
outfile.open("myfile2.txt");
double x,y;
infile>>x>>y;
outfile<<x<<"\t"<<y<<endl;
infile.close();
outfile.close();
当用类fsream定义文件对象时,该对象既能定义输入文件对象,又能定义输出文件对象,所以打开文件时必须在成员函数open()中的参数中给出打开方式(读或写)。
fstream infile,outfile;//定义了两个文件类对象
infile.open("file1.txt",ios::in);
outfile.open("file2.txt",ios:;out);
char ch;
infile>>ch;
outfile<<ch;
infile.close();
outfile.close();
打开文件后,要判断打开文件是否成功。如果打开成功,则文件流对象值为非零值;
如果打开失败,则值为0;
fstream infile,outfile;
infile.open("file1.txt",ios::in);
outfile.open("file2.txt",ios:;out);
if(!infile)
{cout<<"不能打开输入文件"<<endl;exit(0);}
if(!outfile)
{cout<<"不能打开输出文件"<<endl;exit(0);}
打开输入文件时,文件必须存在,
打开输出文件时,如果文件不存在,则系统自动创建新文件,如果文件存在,则删除原文件中的内容,使其成为一个空文件。
二进制文件的读写操作:
若在文件的打开方式中没有特殊说明,打开的文件均为ASCII码文件,若要打开二进制文件,则要特别说明并用特定的读写函数。
fstream infile,outfile;
infile.open(“inf1.dat”, ios::in, ios::binary);
outfile.open(“outf1.dat”, ios::out, ios::binary);
由于二进制文件中的数据不是ASCII码所以不能直接对其读写,必须要通过特定的函数予以转换。
输入函数:
infile.read( char *, int )
输入文件对象名(数据输入的内存地址,一次性读入的字节数)
地址要强制转换成字符指针型
int i;
infile.read((char *)&i, sizeof(int));//从文件中输入1个整型数到i
int a[10];
infile.read((char *)a, 10*sizeof(int));//从文件中输入10个整型数到a
输出函数:
outfile.write( char *, int );
int i=4;
outfile.write((char *)&i, sizeof(int));//向文件输出一个整型数i
int a[10]={0,1,2,3,4,5,6,7,8,9};
outfile.write((char *)a, 10*sizeof(int));//向文件输出一个整型数组a
判断二进制文件是否读到文件尾?
infile.eof( )
当到达文件结束位置时,该函数返回一个非零值;否则返回零。
fstream infile;
infile.open(“data1.dat”,ios::in, ios::binary);
if(!infile)//判断打开是否出错
{ cout<<“Open Error!\n”; exit(1); }
char str[300];
while(!infile.eof())//判断是否读到文件尾
infile.read(str, 300);
实际操作
一.向一个文本文件中写入数据:
#include <iostream>
#include <fstream>//两个类的结合
//fstream是ifstream和ofstream的结合
//既包括了输入操作也包括输出操作
using namespace std;
int main()
{
int a[5];
//ofstream outfile("d:\\桌面\\0209实验.txt", ios::out);
//d:\\表示d盘根目录
//ios::out如果文件不存在,会按照定义的名称创建文件。
//如果原来存在文件,会清空;如果不存在,创建
ofstream outfile("d:\\桌面\\0209实验.txt", ios::app);
//以输出方式打开,数据追加到文件末尾
if (!outfile)
{
cout << "open error" << endl;
return 0;
}
else
{
cout << "请输入数据" << endl;
for (int i = 0; i < 5; i++)
{
cin >> a[i];
outfile << a[i] << " ";
}
}
outfile.close();//关闭文件输出流
return 0;
}
编译器运行结果:(例如我们输入1 2 3 4 5)
桌面上会自动创建一个txt文件。
txt文件会因为这段程序,而被写入1 2 3 4 5 这组数据,效果如下:
二.从一个文本文件中读取数据,并对读取的数据做简单处理。
#include <iostream>
#include <fstream>//两个类的结合
//fstream是ifstream和ofstream的结合
//既包括了输入操作也包括输出操作
using namespace std;
int main()
{
int a[20];
int maxs = -1, index = 0;
ifstream infile("d:\\桌面\\0209shiyan.txt", ios::in);
if (!infile)
{
cout << "oper error" << endl;
return 0;
}
else
{
for (int i = 0; i < 5; i++)
{
infile >> a[i];
cout << a[i] << " ";
if (a[i] > maxs)
{
maxs = a[i];
index = i;
}
}
cout << endl << "maxs is " << maxs << endl;
cout << "pos is " << index << endl;
}
return 0;
}
编译器运行结果:
因为是读取“一”中写入的数据而没有对0209shiyan.txt这个文本文件中的数据做任何修改,因此文本文件中的数据不变。
三.二进制文件的写入操作
#include <iostream>
#include <fstream>
using namespace std;
struct student
{
string name;
int age;
char sex;
};
int main()
{
student stu[3] = { "li",18,'F',"wu",19,'M',"zhang",17,'F' };
ofstream outfile("d:\\桌面\\0209shiyan.txt",ios::out, ios::binary);
//ios::binary 是“将数据转变为二进制的形式储存在文件中”的意思
if (!outfile)
{
cout << "open error" << endl;
exit(0);//代表终止所有程序的意思,和return 0; 功能类似
}
else
{
for (int i = 0; i < 3; i++)
{
outfile.write((char*)(&stu[i]), sizeof(stu[i]));
}
//write函数:write函数第一个参数必须是char*指针类型的数据,
//如果不是这个类型的数据,需要进行强制转换
//第二个参数是写入数据的大小。
outfile.close();
//关闭文件有终止缓冲区运行的作用,文本文件用完之后就要写close函数。
}
return 0;
}
因为程序没有任何实质性的编译器层面的输出,所以编译器显示为0输出。
由于是二进制的形式储存,所以文本文件执行显示层面展示的是一堆乱码,并且每次查看都不太一样。
四.对二进制文件的读取操作
#include <iostream>
#include <fstream>
using namespace std;
struct student
{
string name;
int age;
char sex;
};
int main()
{
student stu[3];
ifstream infile("d:\\桌面\\0209shiyan.txt", ios::out, ios::binary);
if (!infile)
{
cout << "open error" << endl;
exit(0);
}
else
{
for (int i = 0; i < 3; i++)
{
//outfile.write((char*)(&stu[i]), sizeof(stu[i]));
infile.read((char*)&stu[i], sizeof(stu[i]));
}
//read函数:与write函数参数格式要求相同。
//第一个参数 要求必须是char*类型的,第二个参数是读取数据的大小。
infile.close();//infile用完了,就要close它。
//上述代码实现的功能是将二进制文件从文件中读取出来,并储存在了程序的数组之中。
//将程序中的数组存储的内容输出,看看读入的数据是否正确?
for (int i = 0; i < 3; i++)
{
cout << "NO." << i + 1 << endl;
cout << "name:" << stu[i].name << endl;
cout << "age:" << stu[i].age << endl;
cout << "sex:" << stu[i].sex << endl;
}
}
return 0;
}
运行效果:
发现读取到的数据和“三”中给文本文件写入的数据完全一致。
由于本程序只涉及到“读取”操作,因此没有对0209shiyan.txt中的内容做任何修改。
五. 举例
从编译器的运行框中输入一串字符串,挑出其中属于字母的字符,在编译器运行框中输出的同时,将输出结果也储存在一个文本文档中;读取该文本文档中的数据,并将所有小写字母都转化为大写字母,将运行结果储存在另一个文本文档中。
#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;
void save_to_file()
{
ofstream outfile("d:\\桌面\\0209shiyan.txt", ios::out);
//如果不指定位置,不同编译器存储txt文件的位置不同。
if (!outfile)
{
cout << "open error" << endl;
exit(0);
}
else
{
char a[1000];
cin.getline(a, 1000, '\n');
for (int i = 0; i < strlen(a); i++)
if (a[i] >= 'a' && a[i] <= 'z' || a[i] >= 'A' && a[i] <= 'Z')
{
outfile.put(a[i]);
//outfile.put函数:将一个参数携带的数据传入到文本文件中并储存
cout << a[i] << " ";//同时将数据送达显示器
}
cout << endl;
outfile.close();
}
}
void get_from_file()
{
ifstream infile("d:\\桌面\\0209shiyan.txt", ios::in);//从0209shiyan.txt中读入数据
ofstream outfile("d:\\桌面\\0209shiyan1.txt", ios::out);//将结果的数据传出,写到0209shiyan1.txt中
if (!infile||!outfile)
{
cout << "open error" << endl;
exit(0);
}
else
{
char ch;
while (infile.get(ch))
{
if (ch >= 'a' && ch <= 'z')
{
ch -= 32;//将小写字母转化为大写字母
outfile.put(ch);//储存。
}
}
infile.close();
outfile.close();
}
}
int main()
{
save_to_file();
get_from_file();
return 0;
}
运行结果:
文本文档中的效果:
程序使得计算机自主创建了一个文本文档,被我命名为0209shiyan1.txt。
在0209shiyan.txt中
效果是这样的:
在0209shiyan1.txt中,效果是这样的:
六.IO操作的简单应用(代码和举例都在更新和完善中)
一.对《06笔记 输入输出流重载》中代码补充IO操作:
#include <iostream>
#include<fstream>
using namespace std;
class complex
{
private:
double real,imag;
public:
complex() { real = 0; imag = 0; }
complex(double a, double b) { real = a; imag = b; }
complex operator + (complex&);
void showcomplex(){ cout << "(" << real << "," << imag << "i)" << endl; }
//friend complex operator +(complex&, complex&);
friend istream& operator>>(istream&, complex&);//输入流重载的声明
friend ostream& operator<<(ostream&, complex&);//输出流重载的声明
};
inline complex complex::operator+(complex& a)
//函数的返回值类型 上一级::下一级 运算符(数据类型 变量名称)
{
complex c;
c.real = this->real + a.real;
c.imag = this->imag + a.imag;
return c;
}
//写法2
/*
complex operator + (complex& a, complex& b)
{
complex c;
c.real = a.real + b.real;
c.imag = a.imag + b.imag;
return c;
}
*/
//输入流重载
//istream 输入流 ostream 输出流
istream& operator >>(istream &input, complex& c)
{
cout << "请分别输入一个复数的实部和虚部:" << endl;
input >> c.real >> c.imag;
return input;
}
//输出流重载
ostream& operator<<(ostream& output, complex& c)
{
output << "(" << c.real << "," << c.imag << "i)" << endl;
return output;
}
int main()
{
ofstream outfile("d:\\桌面\\complex.txt", ios::out);
ifstream infile("d:\\桌面\\zhengshu.txt", ios::in);
//声明:只有ostream才可以自主创建新的文本文件,
//istream不能,需要用户提前创建并命名,并事先写入数据
complex a, b, c;
infile>> a >> b;
c = a + b;
//infile.close();
a.showcomplex();
b.showcomplex();
c.showcomplex();
cout << c;
outfile << a << endl;
outfile << b << endl;
outfile << c << endl;
infile.close();
outfile.close();
return 0;
}
声明:
//声明:只有ostream才可以自主创建新的文本文件,
//istream不能,需要用户提前创建并命名,并事先写入数据
实现部分:
由上述声明,笔者自行创建了一个文本文件叫做zhengshu.txt,写入数据 1 2 3 4
效果如下:
现在对原代码进行编译,运行效果为:
此时,文本文件complex.txt中的效果如下: