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
系统调用用于打开或创建文件,并返回文件描述符。
#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
系统调用用于从文件中读取数据。它接受文件描述符、缓冲区地址和读取的字节数作为参数。
#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
系统调用用于将数据写入文件。它接受文件描述符、缓冲区地址和写入的字节数作为参数。
#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_SET
、SEEK_CUR
、SEEK_END
)作为参数。
#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
系统调用用于关闭文件。关闭文件后,与文件描述符相关联的资源将被释放。
#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
函数输出错误信息。
#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
函数可以获取文件的详细信息,包括文件类型、权限、大小等。
#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
函数用于删除文件。
#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
函数用于删除目录。
#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
函数也可以用于移动文件。
#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;
}
以上是一些文件和目录操作的基础概念,涵盖了获取文件信息、创建和删除文件、创建和删除目录、以及重命名和移动文件等操作。这些操作在实际应用程序开发中经常用到,根据需求可以选择合适的函数进行调用。