Linux文件I/O基础

2024-02-17 15:37:26 浏览数 (1)

Linux 文件 I/O(Input/Output)基础是 Linux 应用程序开发中的重要组成部分。在 Linux 系统中,文件 I/O 涉及到文件的读取和写入,以及文件描述符、系统调用等概念。以下是 Linux 文件 I/O 的基础知识:

1. 文件描述符

在 Linux 中,每个打开的文件都与一个文件描述符相关联。文件描述符是一个非负整数,表示进程中打开文件的引用。通常,文件描述符的值为 0、1 和 2,分别代表标准输入(stdin)、标准输出(stdout)和标准错误(stderr)。

2. 打开文件

要在 Linux 中进行文件 I/O,首先需要打开文件。open 系统调用用于打开或创建文件,并返回文件描述符。

代码语言:javascript复制
#include <fcntl.h>
#include <unistd.h>

int main() {
    // 打开文件 example.txt,如果不存在则创建,以读写方式打开
    int fileDescriptor = open("example.txt", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);

    // 其他文件 I/O 操作...

    // 关闭文件
    close(fileDescriptor);

    return 0;
}

3. 读取文件

read 系统调用用于从文件中读取数据。它接受文件描述符、缓冲区地址和读取的字节数作为参数。

代码语言:javascript复制
#include <fcntl.h>
#include <unistd.h>
#include <iostream>

int main() {
    int fileDescriptor = open("example.txt", O_RDONLY);
    char buffer[256];

    // 从文件中读取数据到缓冲区
    ssize_t bytesRead = read(fileDescriptor, buffer, sizeof(buffer));

    // 处理读取的数据
    std::cout << "Read " << bytesRead << " bytes: " << buffer << std::endl;

    close(fileDescriptor);

    return 0;
}

4. 写入文件

write 系统调用用于将数据写入文件。它接受文件描述符、缓冲区地址和写入的字节数作为参数。

代码语言:javascript复制
#include <fcntl.h>
#include <unistd.h>

int main() {
    int fileDescriptor = open("example.txt", O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
    const char* data = "Hello, Linux!";

    // 将数据写入文件
    ssize_t bytesWritten = write(fileDescriptor, data, strlen(data));

    // 处理写入的数据...

    close(fileDescriptor);

    return 0;
}

5. 移动文件指针

lseek 系统调用用于在文件中移动文件指针的位置。它接受文件描述符、偏移量和移动的位置(例如 SEEK_SETSEEK_CURSEEK_END)作为参数。

代码语言:javascript复制
#include <fcntl.h>
#include <unistd.h>

int main() {
    int fileDescriptor = open("example.txt", O_RDWR);
    off_t offset = lseek(fileDescriptor, 5, SEEK_SET);  // 将文件指针移动到文件开头后的第 5 个字节

    // 处理文件指针位置...

    close(fileDescriptor);

    return 0;
}

6. 关闭文件

close 系统调用用于关闭文件。关闭文件后,与文件描述符相关联的资源将被释放。

代码语言:javascript复制
#include <unistd.h>

int main() {
    int fileDescriptor = open("example.txt", O_RDWR);

    // 其他文件 I/O 操作...

    // 关闭文件
    close(fileDescriptor);

    return 0;
}

7. 文件 I/O 错误处理

在进行文件 I/O 操作时,需要进行错误处理以处理可能发生的错误。通常,系统调用的返回值为 -1 表示发生了错误,此时可以使用全局变量 errno 获取错误码,并使用 perror 函数输出错误信息。

代码语言:javascript复制
#include <fcntl.h>
#include <unistd.h>
#include <cerrno>
#include <cstring>
#include <iostream>

int main() {
    int fileDescriptor = open("nonexistent_file.txt", O_RDONLY);

    if (fileDescriptor == -1) {
        perror("Error opening file");
        std::cerr << "Error code: " << errno << ", Message: " << strerror(errno) << std::endl;
        return 1;
    }

    // 其他文件 I/O 操作...

    close(fileDescriptor);

    return 0;
}

8. 文件和目录操作

Linux 提供了一系列的文件和目录操作函数,可以用于获取和修改文件和目录的属性。以下是一些常见的文件和目录操作:

获取文件信息

使用 stat 函数可以获取文件的详细信息,包括文件类型、权限、大小等。

代码语言:javascript复制
#include <sys/stat.h>
#include <unistd.h>
#include <iostream>

int main() {
    struct stat fileInfo;
    if (stat("example.txt", &fileInfo) == 0) {
        std::cout << "File size: " << fileInfo.st_size << " bytes" << std::endl;
        std::cout << "File permissions: " << (fileInfo.st_mode & 0777) << std::endl;
        // 其他文件信息...
    } else {
        perror("Error getting file information");
    }

    return 0;
}
创建和删除文件

使用 creat 函数可以创建新的文件,而 unlink 函数用于删除文件。

代码语言:javascript复制
#include <fcntl.h>
#include <unistd.h>

int main() {
    int fileDescriptor = creat("newfile.txt", S_IRUSR | S_IWUSR);
    if (fileDescriptor != -1) {
        // 文件创建成功
        // 其他文件 I/O 操作...
        close(fileDescriptor);
    } else {
        perror("Error creating file");
    }

    // 删除文件
    if (unlink("newfile.txt") == 0) {
        // 文件删除成功
    } else {
        perror("Error deleting file");
    }

    return 0;
}
创建和删除目录

使用 mkdir 函数可以创建新的目录,而 rmdir 函数用于删除目录。

代码语言:javascript复制
#include <sys/stat.h>
#include <unistd.h>

int main() {
    // 创建目录
    if (mkdir("newdir", S_IRWXU | S_IRWXG | S_IRWXO) == 0) {
        // 目录创建成功
    } else {
        perror("Error creating directory");
    }

    // 删除目录
    if (rmdir("newdir") == 0) {
        // 目录删除成功
    } else {
        perror("Error deleting directory");
    }

    return 0;
}
重命名和移动文件

使用 rename 函数可以重命名文件,而 rename 函数也可以用于移动文件。

代码语言:javascript复制
#include <unistd.h>

int main() {
    // 重命名文件
    if (rename("oldfile.txt", "newfile.txt") == 0) {
        // 文件重命名成功
    } else {
        perror("Error renaming file");
    }

    // 移动文件
    if (rename("sourcefile.txt", "targetdir/destinationfile.txt") == 0) {
        // 文件移动成功
    } else {
        perror("Error moving file");
    }

    return 0;
}

以上是一些文件和目录操作的基础概念,涵盖了获取文件信息、创建和删除文件、创建和删除目录、以及重命名和移动文件等操作。这些操作在实际应用程序开发中经常用到,根据需求可以选择合适的函数进行调用。

0 人点赞