流的概念
在C++语言中,数据的输入和输出(I/O)包括对标准输入设备(键盘)和标准输出设备(显示器)、外存磁盘文件、内存中指定字符串储存空间进行输入和输出三个方面,分别简称为标准I/O,文件I/O,串I/O。C++将写入文件和读取文件抽象的说为文件流,三种I/O对应着三种文件流,分别是标准I/O流,文件I/O流和字符串I/O流。
流 | 解释 |
---|---|
标准I/O流 | 内存与标准输入输出设备之间的信息传递 |
文件I/O流 | 内存与外部文件之间的信息传递 |
字符串I/O流 | 内存变量与表示字符串流的数组之间的传递 |
流的类库
#include <fstream>
using namespace std;
头文件’<fstream>'所提供的文件流 | 描述 |
---|---|
ifstream | 输入文件流,用于从文件读取信息 |
ofstream | 输出文件流,用于创建文件和向文件写入信息 |
fstream | 文件流,包含输入文件流和输出文件流的功能 |
虽然fstream看起来很全能,但是实际应用中并不好用。ifstream和ofstream再打开文件时如果文件不存在则会创建文件,而fstream当文件不存在时虽然不报错,但是后续对文件的操作无法生效。
流操作
所有代码都是示意代码,并不能运行。
基础文件I/O
这里我们以ifstream为例,ofstream具有相同的成员函数和操作方式。
- 打开文件
#include <fstream>
using namespace std;
// 第一种打开文件的方式——构造函数
ifstream infile(file_name, open_mode);
// 第二种打开文件的方式——成员函数
ifstream infile;
infile.open(file_name, open_mode);
open_mode1 | 速记 | 说明 |
---|---|---|
ios::out | output (输出) | 指定文件的打开方式为写入,一般为必要参数,但在使用 ofstream 对象时,为默认参数 |
ios::app | append (添加) | 当打开文件用于写入时,会在已有数据之后写入,不覆盖原有内容。使用此种打开方式,每次写入都会置于文件末尾,即便之前更改了位置。 |
ios::trunc | truncate (截断) | 当打开文件时,如果文件存在内容则清空文件内容 |
ios::ate | at end (在结束处) | 以写入方式打开文件,并将文件指针置于末尾。与 ios::app不同之处为,如果改变了指针位置,写入不一定会在文件末尾 |
- 判断文件是否打开成功
#include <fstream>
using namespace std;
ifstream infile;
infile.open(file_name, open_mode);
// 第一种
if(infile) {/*文件打开成功*/};
// 第二种
if(infile.is_open()) {/*文件打开成功*/};
- 关闭文件
#include <fstream>
using namespace std;
ifstream infile;
infile.close();
- 读取文件
#include <fstream>
#include <string> // getline函数需要包含头文件
using namespace std;
ifstream infile;
// 读取一行内容,遇到\n停止,读取成功返回true,遇到文件结尾返回false
getline(infile, char* c);
// 读取一个字符,读取成功返回true,遇到文件结尾返回false
infile.get(char c);
// 读取内容直到分隔符(空格、换行...)
infile>> char* c;
- 写入文件
#include <fstream>
using namespace std;
ofstream outfile;
// 写入字符串c中的全部内容
outfile<< char* c;
// 写入一个字符
outfile.put(char c);
- 获取文件偏移量
#include <fstream>
using namespace std;
ofstream outfile;
ifstream infile;
// ofstream和ifstream的获取文件偏移的方法不可混用
// 两个函数都返回所处位置处的字符在文件中的编号位置
outfile.tellp();
infile.tellg();
- 设置文件偏移量
#include <fstream>
using namespace std;
ofstream outfile;
ifstream infile;
// ofstream和ifstream的设置文件偏移的方法不可混用
outfile.seekp(streampos pos); // pos为字符在文件中的编号位置
outfile.seekp(streamoff off, ios::seek_dir dir); // dir为起始搜索位置,off为相对于dir向文件末尾的偏移量
outfile.seekp(streampos pos); // pos为字符在文件中的编号位置
outfile.seekp(streamoff off, ios::seek_dir dir); // dir为起始搜索位置,off为相对于dir向文件末尾的偏移量
dir | 含义 |
---|---|
ios::beg | 文件流的起始位置(默认值) |
ios::cur | 文件流的当前位置 |
ios::end | 文件流的结束位置 |
由于ios是ifstream和ofstream的一个父类,所以也可以使用ifstream::beg等来使用这些枚举
- 文件状态判断
#include <fstream>
using namespace std;
ifstream infile;
// 读写的过程中出错则返回true
infile.bad();
// 包含bad的情况,另外,读入的数据与容器格式不符时也会报错,例如想读入一个整数却得到一个字母
infile.fail();
// 文件达到末尾时返回true
infile.eof();
// 文件没有读写和格式不符错误,且没有达到文件末尾。即fail和eof都是false时,该函数为true
infile.good();
更精细的文件I/O
- 获得文件的大小
#include <fstream>
using namespace std;
ifstream infile;
infile.seekg(0, infile.end);
int file_length = infile.tellg();
如若想获得某一部分的大小,则可以该部分内容的起始位置和终止位置的序号相减。
- 将文件读入内存
#include <fstream>
using namespace std;
ifstream infile;
infile.seekg(0, infile.end);
int file_length = infile.tellg();
char* buffer = new char[file_length];
infile.read(buffer, file_length);
delete[] buffer;
- 将内存写入文件
#include <fstream>
using namespace std;
// 先将内容读入到内存中
ifstream infile;
infile.seekg(0, infile.end);
int file_length = infile.tellg();
char* buffer = new char[file_length];
infile.read(buffer, file_length);
// 再将内容写入到文件中
ofstream outfile;
outfile.write(buffer, file_length);
delete[] buffer;