linux文件操作

如何使用 C++ 在 Linux 环境下进行文件操作

一、open() 系统调用(Unix/Linux)

1. 核心知识点回顾

  • 函数原型

    1
    2
    3
    4
    5
    6
    #include <fcntl.h>    // 定义 O_RDONLY、O_WRONLY 等标志
    #include <sys/types.h> // 定义 mode_t 类型
    #include <sys/stat.h> // 定义文件权限宏

    int open(const char *pathname, int flags);
    int open(const char *pathname, int flags, mode_t mode);
  • 参数

    • pathname:要打开或创建的文件路径(绝对或相对路径)
    • flags:必选标志,只能选其一(O_RDONLY/O_WRONLY/O_RDWR)和可选标志(O_CREATO_EXCLO_APPENDO_TRUNC 等)。
    • mode:当使用 O_CREAT 标志时需指定权限。创建文件时的权限(如 0644)。
  • 返回值:文件描述符(整数)或 -1(失败)。

  • 特点:无缓冲的底层操作,适合设备驱动、非阻塞 I/O 等场景。

2. 关键标志位

标志 功能描述
O_CREAT 文件不存在时创建
O_EXCL O_CREAT 联用,文件存在则报错
O_TRUNC 打开时截断文件
O_APPEND 追加模式
O_NONBLOCK 非阻塞模式

3. 错误处理

open() 失败时会设置 errno,常见错误码:

  • ENOENT:路径不存在(无 O_CREAT 标志时)。

  • EACCES:权限不足(如尝试写入只读文件)。

  • EEXIST:文件已存在(使用 O_CREAT | O_EXCL 时)。

  • EISDIR:路径是目录而非文件。

4. 相关系统调用

  • close(int fd):关闭文件描述符。

  • read(int fd, void *buf, size_t count):从文件读取数据。

  • write(int fd, const void *buf, size_t count):向文件写入数据。

  • lseek(int fd, off_t offset, int whence):移动文件读写位置。

  • creat(const char *pathname, mode_t mode):等价于 open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode)

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
38
39
40
41
42
43
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main() {
// 打开文件(不存在则创建,存在则截断)
int fd = open("test.txt", O_RDWR | O_CREAT | O_TRUNC, 0644);
if (fd == -1) {
perror("open failed");
return EXIT_FAILURE;
}

// 写入数据
const char *data = "Hello, open()!\n";
ssize_t bytes_written = write(fd, data, strlen(data));
if (bytes_written == -1) {
perror("write failed");
close(fd);
return EXIT_FAILURE;
}

// 移动文件指针到开头
if (lseek(fd, 0, SEEK_SET) == -1) {
perror("lseek failed");
close(fd);
return EXIT_FAILURE;
}

// 读取数据
char buffer[100];
ssize_t bytes_read = read(fd, buffer, sizeof(buffer) - 1);
if (bytes_read == -1) {
perror("read failed");
close(fd);
return EXIT_FAILURE;
}
buffer[bytes_read] = '\0'; // 确保字符串以 '\0' 结尾

printf("Read: %s", buffer);
close(fd); // 关闭文件描述符
return 0;
}

二、C++ 标准库中的文件操作

C++ 提供了更高级的文件流类,基于对象和异常处理,避免了直接使用系统调用的复杂性。

1. <fstream> 库(推荐方案)

  • 主要类

    • std::ifstream:输入文件流(只读)。
    • std::ofstream:输出文件流(只写)。
    • std::fstream:输入 / 输出文件流(读写)。

示例:打开文件并读写

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
#include <fstream>
#include <iostream>
#include <string>

int main() {
// 打开文件(不存在则创建,存在则截断)
std::ofstream outfile("test.txt", std::ios::out | std::ios::trunc);
if (!outfile.is_open()) {
std::cerr << "Failed to open file!" << std::endl;
return 1;
}

// 写入数据
outfile << "Hello, C++ file stream!" << std::endl;
outfile.close();

// 读取文件
std::ifstream infile("test.txt");
std::string line;
if (infile.is_open()) {
while (std::getline(infile, line)) {
std::cout << "Read: " << line << std::endl;
}
infile.close();
}

return 0;
}

2. 文件打开模式(std::ios_base::openmode

模式 功能描述
std::ios::in 输入模式(读取)
std::ios::out 输出模式(写入,默认截断文件)
std::ios::app 追加模式(写入到文件末尾)
std::ios::ate 打开后定位到文件末尾
std::ios::trunc 打开时截断文件(若已存在)
std::ios::binary 二进制模式(避免文本模式转换)

三、C++17 及以后的文件系统库(<filesystem>

C++17 引入了更现代化的文件系统操作 API,提供路径处理、文件状态检查等功能。

1. 文件操作示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <filesystem>
#include <fstream>
#include <iostream>

namespace fs = std::filesystem;

int main() {
fs::path filePath = "test.txt";

// 创建文件并写入
if (std::ofstream file(filePath); file.is_open()) {
file << "Hello, C++17 filesystem!";
file.close();
}

// 检查文件状态
if (fs::exists(filePath)) {
std::cout << "File size: " << fs::file_size(filePath) << " bytes" << std::endl;
fs::remove(filePath); // 删除文件
}

return 0;
}

2. 优势

  • 跨平台:自动处理不同操作系统的路径分隔符(如 /\)。

  • 异常安全:使用 RAII 管理资源,避免手动关闭文件。

  • 功能丰富:支持文件遍历、权限管理、硬链接操作等。