C++标准库-fstream文件流

C++标准库 fstream 用来读写文件。

文件流

C++标准库头文件 #include <fstream> 中包含了三个重要的文件流类:

  • fstream:既可以读文件,也可以写文件
  • ifstream:只能读文件
  • ofstream:只能写文件

文件读写的基本步骤是:

  1. 初始化文件流对象:声明,例如 fstream f 声明了读写文件流对象f
  2. 打开文件:调用 open 方法,例如 f.open("xxx.txt", ios::in)
  3. 读/写文件:读取内容或者写入内容
  4. 关闭文件:调用 close 方法,f.close()

声明文件流对象

如果只是对文件进行 操作,请使用 ifstream;如果只是对文件进行写操作,请使用 ofstream。语法如下:

1
2
3
std::ifstream in;
std::ofstream out;
std::fstream in_out;

打开文件

open 方法打开

open 是三个文件流类的成员方法,可被文件流对象调用以打开文件,实现文件流对象与具体文件的绑定。

open 方法接收两个参数:文件路径,文件操纵模式。

1
2
3
in.open("xxx.txt", std::ios::in);
out.open("yyy.txt", std::ios::app);
in_out.open("zzz.txt", std::ios::in | std::ios::out)

读文件流对象的模式默认为 ios::in,可以缺省。

ios标准库 内置了日常所需的文件操纵模式,包括:

  • ios::in 打开文件用于读取
  • ios::out 打开文件用于写入
  • ios::ate 文件打开后定位到末尾
  • ios::app 追加模式,所有写入添加到文件末尾
  • ios::binary 二进制方式
  • ios::trunc 如果文件已存在则先删除文件

常见的文件操纵模式组合:

  • 读取文本文件:ios::in
  • 读取二进制文件:ios::in | ios::binary
  • 写入为文本文件,文件存在时覆盖写入:ios::out
  • 写入为文本文件,文件存在时追加写入:ios::out | ios::ate 或者 ios::app
  • 写入为文本文件,文件存在时先删除再写入:ios::out | ios::trunc
  • 写入为二进制文件,文件存在时覆盖写入:ios::out | ios::binary

关于写入文件的三种情形,假设我有一个文件内容如下,想要写入的内容是 Fuzhou 和 Guangzhou:

1
2
3
Nanjing
Shanghai
Shenzhen
文件写入方式 结果
覆盖式 Fuzhou
Guangzhou
Shenzhen
追加式 Nanjing
Shanghai
Shenzhen
Fuzhou
Guangzhou
删除式 Fuzhou
Guangzhou

在声明时打开

除了使用 open 方法,在声明文件流对象时可以直接打开文件,语法如下:

1
2
std::ifstream in("xxx.txt");
std::ofstream out("yyy.txt", std::ios::out);

检查文件打开是否成功

通过 if(in_out) 来判断文件是否打开成功。

读取文件

在某些编程语言中,文件流对象打开文件后又叫做 文件句柄。文件句柄本身不存储文件的内容,但我们可以从文件句柄访问整个文件的内容或者写入内容到文件。文件句柄相当于程序和文件之间的一个通道。

文件句柄的读取方法很多。

逐个单词读取至string变量

流运算符的一个特点就是从空白符后的第一个非空白字符开始,读取到下一个空白符为止。所以只能一个单词一个单词的提取。

常见的空白符有空格、制表符、换行符。

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;

int main(){
int x;
vector<int> vec;
ifstream in("data.txt");
if (in) while (in >> x) vec.push_back(x);
for (int x : vec) cout<<x<<" ";
return 0;
}

逐行读取至string变量

getline 函数可以按行(换行符分割)读取文件,并将每行的内容保存在字符串类型的变量var里面:

1
while (getline(文件句柄fh, 迭代变量var)) { ... }

🐖:var中的行字符串不包含末尾的换行符。

这个getline函数从哪里来的? getline函数用于从 ifstream 中按行读取文件内容,ifstream 派生自 istream<istream> 头文件中就定义了这个 getline 函数。

逐行读取至char数组

此外,文件输入流本身也提供了一个 getline 方法:

1
2
3
const int LINE_LENGTH = 100;
char var[100];
while (in.getline(var, LINE_LENGTH)) { ... }

这个 getline 方法就显得笨重了许多,我们需要先预设一个 LINE_LENGTH,这个值要比文件最长的那一行的长度还要长(假设最长行的长度为99,则这个值最小应该设置为100)。然后我们需要声明一个迭代变量var,它是一个长为 LINE_LENGTH 的 字符数组

getline 方法的第一个参数是迭代变量,第二个参数是 LINE_LENGTH。

所以这个 getline 方法实际上是将文件的每一行读进了一个等长的字符数组里面。

写入文件

流运算符

流运算符可以用于写入文本文件,用于二进制文件可能会产生错误。

1
2
ofstream out("output.txt");
out << setw(20) << setfill('#') << setiosflags(ios::left) << "name: " << "barwe" << endl;

关闭文件

尽管程序结束时会自动关闭打开的文件,但为了安全起见,建议手动关闭。

1
2
3
in.close();
out.close();
in_out.close();
>>>>>>>>>>>>> 转载请注明出处 <<<<<<<<<<<<<
0%