文章目录


C++的文件IO(Input,Output)操作就是指对文件进行读写(输入与输出)的操作。输入就是从磁盘上的文件中读取内容到内存中。输出就是将内存中的数据内容输出或者说写入到磁盘的文件中。

一、文件的类型

文件的类型分为文本文件二进制文件,文本文件又称为ASCII文件,它的每个字节存放一个ASCII码,代表一个字符。二进制文件则是把内存中的数据,按照其在内存中的存储形式原样写在磁盘上存放。
我们经常用文本形式存储数据,缺点则是占用存储空间较多。用二进制形式输出数据,节省了转化时间和存储空间,但不能直接以字符的形式输出,所以看不懂。一般根据自己的需要选择使用文本文件还是二进制文件存储。

#include <fstream>
using namespace std;

int main()
{
short var = 20000;
ofstream fs;
fs.open("d:\\123.txt");
fs << var; // 一般使用 << 写文本文件
fs.close();

ofstream fs2;
fs2.open("d:\\456.txt");
fs2.write((const char*)&var, sizeof(short)); // 使用 write函数写二进制文件
fs2.close();

short value = 0;
ifstream fi;
fi.open("d:\\456.txt");
fi.read((char*)&value, sizeof(short)); // 读取二进制文件类型
return 0;
}

文件的写操作:
写文本类型/ASCII码类型的可见字符串:<<、put(put 只能写单个字符到文件)
①、​​​<<​​重写函数:http://www.cplusplus.com/reference/ostream/ostream/operator%3C%3C/

​write()​​ 函数的第一个参数是 char* 类型(也就是一个地址),char * 不一定是字符串,也可能是二进制数据。第二个参数就是要一个长度,要从多长的一块内存数据写到文件中。

文件的读操作:
①、读文本类型/ASCII码类型的文件:>>、get、getline
​​​>>​​​支持的类型详见:http://www.cplusplus.com/referen … eam/operator%3E%3E/
​​​istream::get​​​ 详见:http://www.cplusplus.com/reference/istream/istream/get/
​​​getline()​​​ 函数,该函数是从文件中读取一行数据,直到有换行符 \n,或者达到 getline 的缓冲区大小,或者读到文件末尾。
istream::getline 详见:http://www.cplusplus.com/reference/istream/istream/getline/

②、读取二进制文件类型:read
​​​read()​​​ 函数:http://www.cplusplus.com/reference/istream/istream/read/
从指定的文件中读取数据,读取的数据可以是文本类型的也可以是二进制类型的,把读取到的内容放在第一个参数指针指向的内存中,具体读取的字节数就是靠第二个参数指定。

二、文件操作类详情:

C++文件流:
fstream(输入输出文件流):支持文件的输入与输出操作;
ifstream(输入文件流):支持从文件中输入操作;
ofstream(输出文件流):支持向文件写入的操作;

实际上这几个类都是C++标准模板库STL中提供给我们的,现成的,写好的文件流操作类,我们可以直接拿过来用!
C++本身兼容C语言,所以C语言中的文件读写函数仍然支持,比如:fopen、fread、fwrite、fclose 等等。

文件的打开操作:构造函数与open函数
ofstream fs("z:\\123.txt");
fs.open("z:\\123.txt");

这两种操作都是可以的。当前我们这里只使用了第1个参数,即:传入了文件的路径。实际上open函数有多个参数,第2个参数,表示打开文件的方式,


​ios::in​​:为输入 (

) 而打开文件,文件不存在则创建


​ios::out​​:为输出 (

) 而打开文件,文件不存在则创建,若文件已存在则清空原内容


​ios::ate​​:初始位置:文件尾,常和in、out联合使用


​ios::app​​:文件末尾

追加内容


​ios::trunc​​:如果

文件已存在则先删除该文件


​ios::nocreate​​:文件不存在时产生错误,常和in或app联合使用


​ios::noreplace​​:文件存在时产生错误,常和out联合使用


​ios::binary​​:

二进制方式


ofstream、ifstream、fstream 的open函数或者构造函数都有默认的打开文件的方式,如果不传第2个参数,那么就用默认的,其值如下:

ofstream fs1("123.txt", ios::out);             //(创建文件)写入内容
ifstream fs2("123.txt", ios::in); // 读取内容
fstream fs3("123.txt", ios::in|ios::out); // 以读写方式打开文件


ifstream f("d:\\12.txt", ios::nocreate);   //默认ios::in 的方式打开文件,文件不存在时操作失败
fstream f("d:\\12.dat", ios::in|ios::out|ios::binary); //以读、写方式打开二进制文件
文件打开判断、文件保护

文件保护方式
​​​filebuf::openprot​​​;   //默认的兼容共享方式
​​​filebuf::sh_none​​​;    //独占,不共享
​​​filebuf::sh_read​​​;    //读共享
​​​filebuf::sh_write​​;   //写共享

如何判断文件是否打开成功了呢?open函数的返回值是 void 类型,以下方法都可以:
①、直接 if 判断 fs 对象;
②、用 is_open 方法判断;
③、用 good 方法判断;没有发生任何错误的时候返回true
④、用 fail 方法判断;判断最后一次读取数据的时候是否遇到了类型不配的情况,若是返回true(如果遇到了EOF,该方法也返回true)

小示例:

#include "stdafx.h"
#include <fstream>
#include <iostream>
using namespace std;



int main()
{
ifstream fii("C:\\Users\\xxx\\Desktop\\111.txt");
if(!fii)
{
cout << "file open error!" << endl;
return -1;
};


ifstream fiii("C:\\Users\\xxx\\Desktop\\111.txt");
if (!fiii.is_open())
{
cout << "file open error!" << endl;
return -1;
}

}
读取文件的三种方式
#include <iostream>
#include <fstream>
#include <cassert>
#include <string>


// 逐行读入
void readTxt(string file)
{
ifstream infile;
infile.open(file.data()); //将文件流对象与文件连接起来 或者infile.open(./xxx.txt)
assert(infile.is_open()); //若失败,则输出错误消息,并终止程序运行

string s;
while(getline(infile,s))
{
cout<<s<<endl;
}
infile.close(); //关闭文件输入流
}


//逐个字符读入(忽略空格与回车)
void readTxt(string file)
{
ifstream infile;
infile.open(file.data()); //将文件流对象与文件连接起来
assert(infile.is_open()); //若失败,则输出错误消息,并终止程序运行

char c;
while (!infile.eof())
{
infile >> c;
cout<<c<<endl;

}
infile.close(); //关闭文件输入流
}

//逐个字符读入(包括空格与回车)
void readTxt(string file)
{
ifstream infile;
infile.open(file.data()); //将文件流对象与文件连接起来
assert(infile.is_open()); //若失败,则输出错误消息,并终止程序运行

char c;
infile >> noskipws;
while (!infile.eof()) //达到文件末尾
{
infile>>c;
cout<<c<<endl;

}
infile.close(); //关闭文件输入流
}

eof() 方法用于判断最后一次读取数据的时候是否遇到EOF,即到达文件末尾,若是则返回true。

三、文件指针

在读写文件的时候,每读取或者写入一个字节,磁盘中的文件指针就会向后移动一个字节。可以通过控制指针的位置,以便在我们需要的位置进行读写文件。

  • 文件流提供以下成员函数来读取或配置文件指针:
    tellg() 返回读取文件指针的当前位置
    tellp() 返回写入文件指针的当前位置
    seekg(指针偏移量) 将读取文件指针移到指定位置
    seekg(指针偏移量,参照位置) 将读取文件指针移到指定位置
    seekp(指针偏移量) 将写入文件指针移到指定位置
    seekp(指针偏移量,参照位置) 将写入文件指针移到指定位置

备注:以上函数中的最后一个字母:其中,g代表get,表示读取;p代表put,表示写入
另外,函数参数中的“文件中的位置”和“指针偏移量”为 long整型,以字节为单位。“参照位置”是一个有以下值的枚举:
ios::beg 文件开头计算偏移量
ios::cur 文件当前位置计算偏移量
ios::end 文件结尾计算偏移量
其中,函数seekg(指针偏移量) 和 seekp(指针偏移量),默认从文件开头计算偏移量。

3、使用文件指针获取文件大小:
原理:文件结尾的位置,就代表从文件开始的位置到结尾的字节数,即文件的大小!