目录
介绍
文件I/O是操作系统中的一个基本组件。它允许我们从文件中读取数据并将数据写入到文件中。在这篇博客中,我们将详细了解一些文件I/O的概念以及如何在C程序中使用文件I/O。
文件I/O的概念 文件I/O是指读取和写入文件的操作。在操作系统中,我们通常使用标准I/O库来进行文件I/O操作。标准I/O库提供了一些函数和宏,使我们能够打开、读取、写入和关闭文件。
在文件I/O中,我们使用文件描述符来代表打开的文件。文件描述符是一个整数,它指示了操作系统内核中的文件表中打开文件的位置。每个进程都有一个文件表,其中包含当前打开的文件的信息。
文件I/O库提供了一些函数来操作文件描述符,这些函数包括打开文件、关闭文件、读取文件和写入文件。下面我们将详细介绍这些函数。
打开文件
打开一个文件意味着获取到这个文件的访问句柄(文件描述符fd,在内核管理的打开文件顺序表的下标)
const char *pathname:指针,字符串的地址,字符串是即将打开的文件 O_EXCL:与O_CREAT一起使用,如果文件存在,则返回错误信息,用于只创建新文件 | |
flags:打开方式,可以多个合用,如:有读写,追加,创建--->O_RDWR | O_APPEND | O_CREAT |
注意:当第二个参数中有O_CREAT时,必须加上第三个参数即文件创建权限
文件io的打开指令:
例如,以下代码将打开一个名为“example.txt”的文件,如果文件不存在,则创建该文件。
#include <fcntl.h>
#include <stdio.h>
int main() {
int fd = open("example.txt", O_CREAT | O_RDWR, 0644);//打开文件,存在以只读打开,不存在创建文件(文件权限为0664)
if (fd == -1) {
perror("open");
return 1;
}
// 在此处操作文件
close(fd);//关闭文件
return 0;
}
在这个例子中,我们使用了open()函数来打开“example.txt”文件,以读写方式打开,并且如果文件不存在,则创建该文件。0644是文件许可模式。
读取文件
要从文件中读取数据,我们需要使用read()函数。read()函数接受三个参数,一个是文件描述符,一个是缓冲区用于存储读取的数据,另一个是要读取的字节数。
例如,以下代码打开一个文件,读取其中的数据并将其打印到控制台。
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
int main() {
int fd = open("example.txt", O_RDONLY);
if (fd == -1) {
perror("open");
return 1;
}
char buf[1024];
ssize_t n = read(fd, buf, sizeof(buf)); //读取文件内容
if (n == -1) {
perror("read");
close(fd);
return 1;
}
printf("读取的数据是:\n%.*s\n", (int)n, buf);
close(fd);
return 0;
}
在这个例子中,我们打开了一个文件,然后使用read()函数从文件中读取数据。我们定义了一个缓冲区来存储读取的数据,并将其打印到控制台。
写入文件
要向文件中写入数据,我们需要使用write()函数。write()函数接受三个参数,一个是文件描述符,一个是要写入的数据的指针,另一个是要写入的字节数。
例如,以下代码打开了一个文件,并将一些数据写入该文件。
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
int main() {
int fd = open("example.txt", O_WRONLY | O_APPEND);
if (fd == -1) {
perror("open");
return 1;
}
const char* buf = "这是要写入的数据\n";
ssize_t n = write(fd, buf, strlen(buf));//写入文件
if (n == -1) {
perror("write");
close(fd);
return 1;
}
close(fd);
return 0;
}
在这个例子中,我们打开了一个文件,并使用write()函数将一些数据写入该文件。我们定义了一个字符串来存储要写入的数据,并将其写入文件中。
文件偏移位置
文件偏移位置是指文件中数据的起始位置,通常以字节为单位。在对文件进行读取或写入时,会使用文件偏移位置来确定从哪里开始读取或写入数据。文件偏移位置的初始值为0,每次读取或写入操作完成后,文件偏移位置会自动增加相应的字节数。可以使用系统调用函数lseek来改变文件偏移位置,从而实现对文件的随机读取或写入。
例如,以下代码打开了一个文件,并进行文件偏移。
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
int main() {
// 打开文件
int fd = open("example.txt", O_RDWR);
if (fd == -1) {
perror("open");
return -1;
}
// 从文件开头偏移10个字节
off_t offset = lseek(fd, 10, SEEK_SET);
if (offset == -1) {
perror("lseek");
return -1;
}
// 读取文件中当前位置后的10个字节
char buf[11];
ssize_t n = read(fd, buf, 10);
if (n == -1) {
perror("read");
return -1;
}
buf[n] = '\0';
printf("Read %d bytes: %s\n", n, buf);
// 从当前位置再偏移10个字节
offset = lseek(fd, 10, SEEK_CUR);
if (offset == -1) {
perror("lseek");
return -1;
}
// 写入数据到当前位置
char *data = "Hello World";
n = write(fd, data, 11);
if (n == -1) {
perror("write");
return -1;
}
// 关闭文件
if (close(fd) == -1) {
perror("close");
return -1;
}
return 0;
}
在这个例子中,我们使用open函数打开了名为example.txt的文件,并将文件标识符存储在变量fd中。然后,我们使用lseek函数将文件偏移位置从文件开头移动10个字节。接下来,我们使用read函数读取当前位置之后10个字节的数据并将其存储在buf数组中。然后,我们再次使用lseek函数将文件偏移位置从当前位置再移动10个字节。最后,我们使用write函数将字符串"Hello World"写入文件的当前位置。
关闭文件
当我们完成对文件的操作时,我们需要使用close()函数来关闭文件。close()函数接受一个文件描述符作为参数,然后将该文件描述符从文件表中删除。这样做可以释放文件描述符,以便该文件描述符可用于其他文件。
总结
文件I/O是操作系统中的一个基本组件,它允许我们读取和写入文件。在文件I/O中,我们使用文件描述符来代表打开的文件。文件I/O库提供了一些函数和宏,使我们能够打开、读取、写入和关闭文件。在使用文件I/O时,我们应该始终记住要关闭已打开的文件,并注意错误处理。