C++文件操作

背景

如果将数据都写入到内存中,那么程序停止运行后,内存就会被全部回收,数据也随之消失。这并不是我们想要的。
将数据写入到硬盘中,就可以永久保存,下次运行程序之后读取即可。

专业术语

  • 文件的输入

即读取文件内容。

  • 文件的输出

即往文件里面写入数据。

关于C++文件操作

  • 这里我们利用头文件fstream来对文件进行操作。所以需要引入头文件:#include<fstream>
  • 头文件fstream中定义了很多类,包括ifstream、ofstream和fstream等类。通过这些类,就可以对文件进行写入和读取了。
  • ifstream用于读取文件
  • ofstream用于写入文件
  • fstream既可以用于读取,也可以用于写入。

普通文件和二进制文件

C++有两种文件类型,普通文件和二进制文件。

普通文件

普通文件类似于txt文本文件,存放的内容为字符。
普通文件为明文存取,用户只要得到这个文件,就能看到里面的内容。
因为普通文件时明文存取,所以不适合存放密码等信息。

二进制文件

二进制文件在存储空间中由0和1组成,只有用户知道怎么去分析这些0和1,进而知道此文件的真实信息。
所以二进制文件更为适合存放密码等信息(相对来说)。
如果强制打开此二进制文件,就会出现乱码。(因为打开此文件的软件也不知道如何解析)

  • 在C++中,常常用于存取对象

普通文件的读写

普通文件的输出(写入)
ofstream outfile;	            //输出文件流
outfile.open("test.txt", ios::out );
if (! outfile.is_open())        //打开失败则退出
{ cout << "Error opening file"; exit (1); }
outfile.write("123456",6);		//写入6字节
outfile.close();	            //关闭文件

解释:

  1. 创建对象,通过此对象对文件进行操作。
  2. 打开文件,指定打文件的路径和打开方式(输出或输入)。
  3. 判断打开文件是否成功,打开失败则退出程序。
  4. 写入文件,给出写入的内容和写入的字节数。
  5. 关闭文件。

其中:

  • ios::out是操作属性,out表示文件输出。
    • 如果文件存在,则清空文件。
    • 如果文件不存在,则创建文件。
  • ofstream中的o表示output输出,它实例化的对象默认为ios::out,所以这里可以省略第二个参数ios::out。
  • 有很多原因会造成文件打开失败:
    • 其他程序占用此文件(被其他程序打开了此文件),所以我们最后一定不要忘记关闭这个文件。
    • 磁盘损坏。
    • 文件损坏。
    • 没有权限。(管理员没有授予当前用户权限)
    • 成员函数is_open()用于判断文件是否打开成功,成功返回true。
  • outfile.write("123456",6)表示写入的内容为"123456",写入6个字节。
普通文件的输入(读取)

文件的输入和前面的例子套路类似

ifstream infile;
infile.open("test.txt", ios::in );
if (! infile.is_open())  //打开失败则退出
{ cout << "文件打开失败"; exit (1); }
char buffer;
while (infile.get(buffer)){  //如果读文件到达文件末尾,返回false。
    cout << buffer;
}
infile.close(); //关闭文件

解释:

  1. 创建对象,通过此对象对文件进行操作。
  2. 打开文件,指定打文件的路径和打开方式(输出或输入)。
  3. 判断打开文件是否成功,打开失败则退出程序。
  4. 读取文件。
  5. 关闭文件。

关于读取文件:

  • infile.get(buffer)表示读取一个字符,保存到变量buffer中。如果读取成功,则返回true,否则返回false。

二进制文件的读写

C++常将对象写入二进制文件中

类中通常会有不同类型的变量,如Student中的char name[10]int age
如果将很多学生都写入文件,将name和age分开。那么读取的时候就会变得非常麻烦,因为他们占用的字节数不一样,而且每个人的名字的字数也不一样。
如果使用二进制,就会变得非常方便。

二进制文件的输出(写入)
#include<iostream>
#include<fstream>
using namespace std;
class Student{
public:
    char name[10];
    int age;
    char classroom[10];
    Student(char *name,int age,char classroom[10]){
        strcpy_s(this->name, name);
        this->age=age;
        strcpy_s(this->classroom,classroom);
    }
};
int main(){
    Student s1("张三",18,"1班");
    Student s2("李四",20,"2班");

    //二进制输出
    ofstream outfile;	        //输出文件流
    outfile.open("test.bin", ios::out | ios::binary );
    if (! outfile.is_open())    //打开失败则退出
    { cout << "Error opening file"; exit (1); }
    outfile.write((char*)&s1, sizeof(s1));      //写入对象s1
    outfile.write((char*)&s2, sizeof(s2));      //写入对象s2
    outfile.close();	        //关闭文件
}

解释:

  • 通常用后缀.bin来表示二进制文件,打开属性为ios::binary。
  • 不同的属性组合用或运算ios::out | ios::binary表示。
  • 写入对象时,需要将对象转化为基本数据类型,这里将s1和s2转化为了char类型。
  • 写入对象时,同样需要指定写入大小,我们可以借用sizeof来自动判断对象的大小。
  • 这个例子依次写入了s1和s2。
二进制文件的输入(读取)
#include<iostream>
#include<fstream>
using namespace std;
class Student{
public:
    char name[10];
    int age;
    char classroom[10];
    Student(char *name,int age,char classroom[10]){
        strcpy_s(this->name, name);
        this->age=age;
        strcpy_s(this->classroom,classroom);
    }
};
int main(){
   Student s("",0,"0班");
   //二进制输入
   ifstream infile;
   infile.open("test.bin", ios::binary );
   if (! infile.is_open())  //打开失败则退出
   { cout << "Error opening file"; exit (1); }
   while(infile.read((char *)&s, sizeof(s))) { //一直读到文件结束
       int readedBytes = infile.gcount(); 		//看刚才读了多少字节
       cout<<"读取"<<readedBytes<<"字节"<<endl;
       cout << s.name << " " << s.age << " " << s.classroom<< endl;
   }
}

结果:

张三 18 1班
李四 20 2

解释:

  • 变量s用于保存读取的内容
  • (infile.read((char *)&s, sizeof(s))表示读取数据到变量s中,指定读取的大小,函数会以char类型读取,自动转化为Student的数据成员各自的类型。
  • infile.gcount()可以得到上一次读取的字节数。
  • 通过while循环,依次读取所有的对象。(如上例中的s1和s2)

读取模式

前面的例子中:ios::out表示的就是读取模式。
ios::out表示输出。

常用的模式:

  • ios::in //打开文件用于读取
  • ios::out //打开文件用于写入
  • ios::app //追加模式。所有写入都追加到文件末尾
  • ios::ate //文件打开后将指针定位到文件末尾(常和fstream结合)
  • ios::trunc //文件存在则清空
  • ios::binary //二进制方式读写

小贴士:

ifstream创建的对象默认就是ios::in。
ofstream创建的对象默认就是ios::out。
fstream需要手动指定输入或输出。

多种模式一起使用:

ios::in | ios::binary

举例:

使用fstream、二进制、输出、追加的方式打开文件:

fstream file;
file.open("test.bin", ios::binary | ios:out | ios::ate  );

成员函数

fstream file;   //定义对象
file.open("test.bin", ios:out | ios:in  );
file.is_open()	        //是否打开成功
file.eof()		//读指针是否到达结尾
file.read (buffer, 6);		//读出6字节
file.write("123456",6);		//写入6字节

文件指针

C++中读取文件是通过指针来读取的。
文件的位置决定下一个读取的字符、下一个写入字符的位置。

获取指针的位置:
tellg()		//得到当前读指针位置
tellp()		//得到当前写指针位置
修改指针的位置:
seekg(-4,ios::cur)	//读指针当前位置前移4个字节
seekp(-4,ios::cur)	//写指针当前位置前移4个字节

其中:

ios::cur表示当前指针位置
ios::beg表示从流开始位置计算的位移(即文件开头)
ios::end表示从流末尾处开始计算的位移(即文件结尾)


posted @ 2020-05-16 19:56  NetRookieX  阅读(87)  评论(0编辑  收藏  举报