# 一、C++ 文件 IO 读写

参考教程:C++ 文件和流

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

tellg()  返回读取文件指针的当前位置
tellp()  返回写入文件指针的当前位置
seekg(指针偏移量)  将读取文件指针移到指定位置
seekg(指针偏移量,参照位置)  将读取文件指针移到指定位置
seekp(指针偏移量)  将写入文件指针移到指定位置
seekp(指针偏移量,参照位置)  将写入文件指针移到指定位置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <fstream>
#include <iostream>

using namespace std;

int main()
{
//write file
ofstream outFile;
outFile.open("myfile.txt", ios::out|ios::app); //追加方式打开
// outFile.open("myfile.txt", ios::out|ios::trunc); //截断方式打开

// if(!outFile) {
if(outFile.is_open()) {
cout << "Writing data to myfile.txt" << endl;
outFile.seekp(10); //写指针移位,可选参数 ios::cur、ios::beg、ios::end
for(int i = 0; i < 3; ++i) {
outFile << "data" << i << endl;
} outFile.close();
}

//read file
ifstream inFile;
inFile.open("myfile.txt", ios::in); //读模式打开,ios::in 为默认参数,可不加

if(inFile.is_open()) {
cout << "Reading data from myfile.txt : " << endl;
inFile.seekg(5); //读指针移位,可选参数 ios::cur ios::beg ios::end
while(!inFile.eof()) {
string readStr;
inFile >> readStr;
cout << readStr << endl;
} inFile.close();
}

return 0;
}

1
istream& read(char* s, streamsize n);

作用:Read block of data,从输入流中读取数据然后写入 buffer 中

Extracts n characters from the stream and stores them in the array pointed to by s.

This function simply copies a block of data, without checking its contents nor appending a null character at the end.

If the input sequence runs out of characters to extract (i.e., the end-of-file is reached) before n characters have been successfully read, the array pointed to by s contains all the characters read until that point, and both the eofbit and failbit flags are set for the stream.

具体例子:

1
2
3
4
5
ifstream is(file.c_str(), ios::binary);
msgpack::unpacker unpack_;
unpack_.reserve_buffer(n);
is.read(unpack_.buffer(), n);
unpack_.buffer_consumed(n);

# 二、相关函数

# 2.1 std::ifstream & std::ofstream

std::ifstreamstd::ofstream 是 C++ 标准库中的两个类,用于文件输入和文件输出操作。它们分别用于读取文件和写入文件。

  1. std::ifstream (文件输入流):
    • std::ifstream 是 C++ 标准库中的一个类,用于从文件中读取数据。
    • 它提供了打开文件、读取文件内容以及关闭文件的功能。
    • 可以用于读取文本文件和二进制文件的内容。
    • 通常与文件流操作符(如 >> )一起使用,以从文件中提取数据到程序中。
    • 通常用于读取文本文件中的文本行、数字、配置文件等信息。

以下是一个示例,展示了如何使用 std::ifstream 打开文件并读取其内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <fstream>
#include <iostream>

int main() {
std::ifstream inputFile("example.txt");
if (inputFile.is_open()) {
std::string line;
while(std::getline(inputFile, line)) {
std::cout << line << std::endl;
} inputFile.close();
} else {
std::cout << "Unable to open file." << std::endl;
}
return 0;
}

  1. std::ofstream (文件输出流):
    • std::ofstream 是 C++ 标准库中的一个类,用于将数据写入文件。
    • 它提供了打开文件、将数据写入文件以及关闭文件的功能。
    • 可以用于创建文本文件和二进制文件,并将数据写入文件中。
    • 通常与文件流操作符(如 << )一起使用,以将数据从程序写入文件中。
    • 通常用于生成日志、配置文件、数据文件等。

以下是一个示例,展示了如何使用 std::ofstream 创建文件并将数据写入其中:

1
2
3
4
5
6
7
8
9
10
11
12
#include <fstream>

int main() {
std::ofstream outputFile("output.txt");
if (outputFile.is_open()) {
outputFile << "Hello, World!" << std::endl;
outputFile.close();
} else {
std::cout << "Unable to create or open file." << std::endl;
}
return 0;
}

这些类提供了对文件的高级文件输入和输出操作,使得文件处理变得相对容易。在使用它们时,确保在打开文件后检查文件是否成功打开以及在完成操作后关闭文件以确保资源的释放。

常用函数:

1
2
3
4
5
6
7
8
9
is_open()
open()、close()
good()、bad()
fail()
eof()
read()、write()
seekp()、tellp()
seekg()、tellg()
clear()

这些函数基本就都是对文件流进行一些状态判断、数据读写,都是对关联的某个文件进行操作。
这里需要辨析的是 seek 和 tell 函数,p 表示写入位置(put),g 表示读取位置(get),seek 用于写入,tell 用于读取
然后这个 clear 并不是清空文件内容,而是清除之前的流的错误状态标志,以允许继续文件操作
在 open 时 mode 通常为 std::ios::binary | std::ios::instd::ios::binary | std::ios::out

参考链接:
https://en.cppreference.com/w/cpp/io/basic_ifstream
https://en.cppreference.com/w/cpp/io/basic_ofstream

# 2.2 access

在 C++ 中, access 函数用于检查文件系统中文件或目录的访问权限和存在性。它的一般语法如下:

1
2
#include <unistd.h>
int access(const char *pathname, int mode);

  • pathname 是要检查的文件或目录的路径名。
  • mode 是一个整数,用于指定要检查的权限。常见的权限标志包括:
    • F_OK :用于检查文件或目录的存在性。
    • R_OK :用于检查读权限。
    • W_OK :用于检查写权限。
    • X_OK :用于检查执行权限。

access 函数将返回一个整数值,表示检查的结果。如果文件或目录存在且拥有指定的权限,它将返回 0;否则,返回 -1,并设置 errno 全局变量以指示错误类型。

这个函数通常用于在打开文件之前检查文件是否存在并具有所需的权限。例如,你可以使用 access 函数来检查文件是否可读,以避免在试图打开一个不可读的文件时出现错误。以下是一个示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <unistd.h>

int main() {
const char *filename = "example.txt";
if (access(filename, R_OK) == 0) {
std::cout << "File is readable." << std::endl;
// 打开文件并进行读取操作
} else {
std::cerr << "File is not readable or does not exist." << std::endl;
}
return 0;
}

这个示例首先使用 access 函数检查文件的可读性,然后根据结果执行相应的操作。

# 三、读写范例模板

# 3.1 文件读

1
2
3
4
5
6
7
8
9
10
11
12
std::ifstream myFile(filename, std::ios::binary);
if (!myFile.is_open()) {
std::cerr << "cant open file" << std::endl;
}

myFile.seekg(0, std::ios::end);
std::streampos fileSize = myFile.tellg();
myFile.seekg(0, std::ios::beg);

std::vector<char> file_vector(file_size);
myFile.read(file_vector.data(), fileSize);
myFile.close();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
#include <fstream> // std::ifstream
#include <vector> // std::vector

int main() {
std::ifstream input_file("input.png", std::ios::binary);
if(!input_file.is_open()) {
std::cerr << "open input failed" << std::endl;
return 1;
}

input_file.seekg(0, std::ios::end);
std::streampos file_size = input_file.tellg();
input_file.seekg(0, std::ios::beg);

std::vector<char> file_vector(file_size);

input_file.read(file_vector.data(), file_size);
input_file.close();

std::ofstream output_file("output.png", std::ios::binary);
if(output_file.is_open()) {
output_file.write(file_vector.data(), file_size);
output_file.close();
std::cout << "save new output" << std::endl;
}

return 0;
}

# 3.2 文件写

通用模板:

1
2
3
4
5
6
7
8
std::ofstream myFile("filename", std::ios::binary);
if(myFile.is_open()) {
//...文件写操作...

myFile.close();
} else {
std::cout << "open file error" << std::endl;
}

在初始化构造 ofstream 对象时, std::ios::binary 为可选项,决定是否生成二进制文件还是普通文本文件。文件的写操作可以通过 << 运算符对 ofstream 对象进行写入,也可以通过 write 函数进行写入。

1
2
3
4
5
6
7
8
9
10
11
std::ofstream myFile("filename.txt");
if(myFile.is_open()) {
for(int i = 0; i < 640*480; i++) {
myFile << iiiqData[i] << ",";
} myFile << "\n";

myFile.close();
std::cout << "save file done" << std::endl;
} else {
std::cout << "create file fail" << std::endl;
}

如果是通过 write 函数进行数据的写入,通常会将数据指针 cast 成 char* 类型表示字节流,
然后 write(数据指针,数据长度)

1
2
3
4
5
6
7
std::ofstream myFile("iiData.bin", std::ios::binary);
if(myFile.is_open()) {
myFile.write(reinterpret_cast<char*>(&iiData[0]), iiData.size());
myFile.close();
} else {
std::cout << "open file error" << std::endl;
}

1
2
3
4
5
6
7
8
std::ofstream myFile("/home/pcai/Music/temp/raw.bin", std::ios::binary);
if (myFile.is_open()) {
myFile.write(reinterpret_cast<char*>(data), frame_length);
myFile.close();
std::cout << "Data has been written to raw.bin" << std::endl;
} else {
std::cerr << "Unable to open the output file." << std::endl;
}

更新于

请我喝杯咖啡吧~

Rick 微信支付

微信支付

Rick 支付宝

支付宝