linux

Linux C++如何实现高效的文件I/O操作

小樊
40
2026-01-01 14:35:05
栏目: 编程语言

在Linux环境下使用C++进行高效的文件I/O操作,可以采用以下几种方法和技术:

1. 使用标准库的<fstream>

标准库提供了std::ifstreamstd::ofstream来进行文件的读写操作。虽然简单易用,但在性能上可能不是最优的。

#include <fstream>
#include <iostream>

int main() {
    std::ifstream infile("example.txt");
    std::ofstream outfile("output.txt");

    if (!infile.is_open() || !outfile.is_open()) {
        std::cerr << "Error opening files!" << std::endl;
        return 1;
    }

    std::string line;
    while (std::getline(infile, line)) {
        outfile << line << std::endl;
    }

    infile.close();
    outfile.close();
    return 0;
}

2. 使用mmap进行内存映射

内存映射文件可以显著提高大文件的读写性能,因为它允许直接在内存中操作文件数据。

#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <iostream>

int main() {
    int fd = open("example.txt", O_RDONLY);
    if (fd == -1) {
        std::cerr << "Error opening file!" << std::endl;
        return 1;
    }

    struct stat sb;
    if (fstat(fd, &sb) == -1) {
        std::cerr << "Error getting file size!" << std::endl;
        close(fd);
        return 1;
    }

    char* addr = static_cast<char*>(mmap(nullptr, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0));
    if (addr == MAP_FAILED) {
        std::cerr << "Error mapping file!" << std::endl;
        close(fd);
        return 1;
    }

    // Process the file data in memory
    std::cout << addr << std::endl;

    if (munmap(addr, sb.st_size) == -1) {
        std::cerr << "Error unmapping file!" << std::endl;
    }
    close(fd);
    return 0;
}

3. 使用sendfile进行零拷贝

sendfile系统调用可以在两个文件描述符之间直接传输数据,避免了数据在内核空间和用户空间之间的多次拷贝。

#include <sys/sendfile.h>
#include <fcntl.h>
#include <unistd.h>
#include <iostream>

int main() {
    int src_fd = open("source.txt", O_RDONLY);
    int dst_fd = open("destination.txt", O_WRONLY | O_CREAT, 0644);
    if (src_fd == -1 || dst_fd == -1) {
        std::cerr << "Error opening files!" << std::endl;
        return 1;
    }

    off_t offset = 0;
    ssize_t bytes_sent = sendfile(dst_fd, src_fd, &offset, 1024);
    if (bytes_sent == -1) {
        std::cerr << "Error sending file!" << std::endl;
    }

    close(src_fd);
    close(dst_fd);
    return 0;
}

4. 使用异步I/O

异步I/O允许程序在等待I/O操作完成时继续执行其他任务,从而提高程序的并发性和效率。

#include <aio.h>
#include <fcntl.h>
#include <unistd.h>
#include <iostream>

int main() {
    int fd = open("example.txt", O_RDONLY);
    if (fd == -1) {
        std::cerr << "Error opening file!" << std::endl;
        return 1;
    }

    char buffer[1024];
    struct aiocb cb;
    memset(&cb, 0, sizeof(cb));
    cb.aio_fildes = fd;
    cb.aio_buf = buffer;
    cb.aio_nbytes = sizeof(buffer);
    cb.aio_offset = 0;

    if (aio_read(&cb) == -1) {
        std::cerr << "Error starting async read!" << std::endl;
        close(fd);
        return 1;
    }

    // Do other work while the read is in progress

    while (aio_error(&cb) == EINPROGRESS) {
        // Wait for the read to complete
    }

    ssize_t bytes_read = aio_return(&cb);
    if (bytes_read == -1) {
        std::cerr << "Error reading file!" << std::endl;
    } else {
        std::cout << "Read " << bytes_read << " bytes: " << std::string(buffer, bytes_read) << std::endl;
    }

    close(fd);
    return 0;
}

5. 使用缓冲区

合理使用缓冲区可以减少系统调用的次数,从而提高I/O性能。

#include <fstream>
#include <iostream>

int main() {
    std::ofstream outfile("output.txt", std::ios::out | std::ios::binary);
    if (!outfile.is_open()) {
        std::cerr << "Error opening file!" << std::endl;
        return 1;
    }

    const size_t buffer_size = 1024 * 1024; // 1MB buffer
    char* buffer = new char[buffer_size];

    std::ifstream infile("example.txt", std::ios::in | std::ios::binary);
    if (!infile.is_open()) {
        std::cerr << "Error opening file!" << std::endl;
        delete[] buffer;
        outfile.close();
        return 1;
    }

    while (infile.good()) {
        infile.read(buffer, buffer_size);
        outfile.write(buffer, infile.gcount());
    }

    delete[] buffer;
    infile.close();
    outfile.close();
    return 0;
}

通过结合这些技术和方法,可以在Linux环境下实现高效的文件I/O操作。选择合适的方法取决于具体的应用场景和需求。

0
看了该问题的人还看了