基本文件处理
- 文件处理:c++中文件处理借助相应的文件处理类来实现,即学习文件处理就是在学习文件处理类的使用,与文件处理相关的一些类有:
- std::filesystem::path 即定义在std空间的filesystem子空间的path类,用于处理文件路径,需要c++17支持,且需要包含头
- std::ifstream 文件输入流对象,用于写入数据的相关操作,需要包含头
- std::ofstream 文件输出流对象,用于读取数据的相关操作,需要包含头
- std::fstream 文件输入输出流对象,用于读取或写入数据的相关操作,需要包含头
path类
-
声明格式:需要包含头且需要c++17支持,path类定义在std空间中,如声明;
#include <filesystem> std::filesystem::path p1{"file_name.txt"}; //...
注: 空间限定代码较长可采用namespace为命名空间定义别名(注意:using是为类型定义别名),如:
#include <filesystem> namespace sf = std::filesystem; //... sf::path p1{"file_name.txt"}; //...
当然,也可以直接使用using直接导入该类:using std::filesystem::path;
-
构造函数:一般而言,path类的构造函数为一个字符串,该字符串包含的信息即所处理文件的所在路径,应尽量使用相对路径而避免使用绝对路径 [ 1 ] ^{[1]} [1],如:
std::filesystem::path p1{"d:\clanguage\vs\study\c++文件处理相关\test.txt"}; //避免 std::filesystem::path p2{"test.txt"}; //推荐
注:当有必要采用绝对路径时,也不推荐上述写法,因为其中的路径分隔符’'容易被编译器视作转义字符而出错,解决的办法有三种:
-
用’/'代替:path p1{“d:/clanguage/vs/study/c++文件处理相关/test.txt”};
-
用生字符串:path p1{R"(d:\clanguage\vs\study\c++文件处理相关\test.txt)"};(生字符串:形式为R"(…)"的字符串,括号中为字符串的内容,R必须大写,编译器不会对生字符串中的任何内容进行转义或更改)
-
双重转义:path p1{“d:\\clanguage\\vs\\study\\c++文件处理相关\\test.txt”};
-
推荐使用前两种方式
-
-
常用成员函数:
- empty(): 判断内容(即路径地址)是否为空
-
常用友元函数:
- exists():判断所储存路径是否实际存在
注:filesystem中的space类可以用于得到磁盘空间信息
ifstream类
-
用于仅作读取操作的文件处理类
-
声明格式:需要包含头,声明格式如:
//e.g. #include <fstream> //... std::ifstream file1{"test.txt"}; //...
当然信息也可由path类携带传入,如:
std::ifstream file1{p1}; //p1为已声明的path类对象
-
常用成员函数:
- fail():判断打开文件是否失败,常用于声明对象后作判断
ofstream类
-
用于仅作写入操作的文件处理类
-
声明格式:需要包含头,声明格式如:
//e.g. #include <fstream> //... std::ofstream file1{"test.txt"}; //...
-
成员函数:
- fail():判断打开文件是否失败,常用于声明对象后作判断
fstream类
-
用于多种操作组合的文件操作类,兼容ifsteam和ofstream
-
声明格式:需要包含头,构造时需要第二个参数指定以何种操作方式打开 [ 1 ] ^{[1]} [1],如:
#include <fstream> //... std::fstream file1{"test.txt", std;;ios::out | std::ios::app}; //...
-
成员函数:
- fail():判断打开文件是否失败,常用于声明对象后作判断
- write(char* data,unsigned data_size):用于向文件中以字节流的形式写入信息,第一个为包含信息的参数必须是字符指针类型 [ 2 ] ^{[2]} [2],第二个为写入的信息字节数,可用sizeof()取得
- read(char* buf,unsigned buf_size):用于从文件中以字节流的形式读取信息,第一个为储存读取的信息的参数必须为字符指针类型,第二个为最大读取字节
- eof():判断当前文件光标是否到文件末尾
- put(char ch):写入一个字符到当前光标后,光标后移
- get():从当前光标后读取一个字符,光标后移
- close():用于对文件操作完成后手动关闭文件,如果不是打算关闭后重新打开,则可以不用手动调用该函数,一般文件操作类的析构函数会自行调用该函数
- operator << :重载了输出流运算符
- operator >> :重载了输入流运算符
- getline(file_type file, string str, char divider):需要包含头文件,用于读取特定分隔符之前的所有信息,第一个参数为文件操作类对象,第二个为string类对象,用于储存读取的信息,第三个为指定分隔符,默认为’\n’
注[1]:指定的打开方式类定义在std::ios空间中,调用时需要以std::ios::out形式,可以同时指定多种打开方式(如:追加写入,覆盖写入,写入读取等),多种打开方式之间使用 | 进行连接,如上,常用的打开方式有:
- 打开写入:std::ios::out
- 打开读取:std::ios::in
- 打开在文件末尾追加:std::ios::app
- 打开将光标置于末尾:std::ios::ate
- 打开且舍弃原内容:std::ios::trunc
- 以二进制方式打开:std::ios::binary
注[2]:将不是字符指针类型的信息使用write写入时,需要将其作为第一个参数就需要强制转换为字符指针类型,使用关键字reinterpret_cast<>(),使用方式如:
//e.g.
long long data;
std::fstream file1{"test.txt",std::ios::out | std::ios::trunc};
//...
file1.write(reinterpret_cast<char *>(&data), sizeof(data));
//...
(static_cast<>()用于普通数据类型转换,dynamic_cast<>()用于基类派生类上下转换,reinterpret_cast<>()用于将地址的不同类型进行转换,或是将地址转换为普通类型)
文件光标
- 在对文件进行操作时会存在两个文件光标,用于表明当前对文件信息操作的位置,一个是写操作的位置,一个是读操作的位置,无论是读还是写,都是从当前文件光标的位置后进行的,并且在操作完成后,光标会相应后移,当然也可以手动改变光标的位置.
- 位置信息变量:定义在std::ios中,有
- 文件首:std::ios::beg
- 文件尾:std::ios::end
- 当前光标位置:std::ios::cur
- 文件光标函数:属于文件操作类的成员函数,这里位置信息变量参数以pos表示
- seekg(pos)或seekg(int length,pos):seekg用于重新放置读取光标,pos为重新放置的位置,第二个重载的int参数表示相较于pos差距多少字节(正数表示向右,负数表示向左)
- seekp(pos)或seekp(int length,pos):seekp用于重新放置写入光标
- tellg():用于得到当前读取光标所在位置,返回距文件首的字节数
- tellp():用于得到当前写入光标所在位置,返回距文件首的字节数