文件I/O操作函数
open()
open()
是一个系统调用,用于在 Unix-like 操作系统中打开文件或创建新文件。它提供了对文件的访问和操作。
函数原型如下:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.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_CREAT
: 如果文件不存在,则创建文件O TRUN
: 如果文件存在并且为写入而打开,则将其截断为空文件O_APPEND
:在每次写入时将数据追加到文件未尾
- 可选参数
mode
仅在创建新文件时使用,指定文件的权限。它定义了所有者、所属组和其他用户对文件的读取、写入和执行权限。flag带O_CREAT
选项时可以用来创建文件,这时必须带该参数用来指定创建文件的权限模式,如066。 否则不需要。(示例代码)
int fd;
fd = open(“text.txt”, O_RDWR|O_CREAT|O_TRUNC, 0666);
fd = open(“text.txt”, O_WRONLY|O_APPEND);
open()
函数返回一个非负整文件描述符(file descriptor) ,并且该文件描述符是当前进程最小、未使用的文件描述符数值。用于后对文件进行读取、写入和其他操作。如果返回值为 -1,则表示打开文件发生错误,并设置全局变量 errno
来指示具体的错误信息。
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main() {
int fd = open("example.txt", O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
if (fd == -1) {
perror("无法打开文件");
return 1;
}
// 对文件进行其他操作...
close(fd);
return 0;
}
在上述示例中,我们使用 opon()
函数打开或创建一个名为"examdle.txt"的文件,并进行错误检查,我使用 O_WRONLY
标志以只写方式打开文件,并使用 O_CREAT
标志来创建文件(如果文件不存在)。我们还用 S_IRUSR
、S_IWUSR
来没置文的权限为读和写入权限。然后,我们可以对文件进行其他操作,最后使用 close()
函数关闭文件描述符。
cerate()
int creat(const char *path, mode_t mode);
此函数用来创建一个新文件并返回其fd
。它等价于 open(path, O_WRONLY|O_CREAT|O_TRUNC, mode);
int fd;
fd=creat(“text.txt”, 0644);
read()
read()
是一个在 Unix/Linux 系统下用于从文件描述符中读取数据的系统调用函数。它的原型如下:
#include <unistd.h>
ssize_t read(int fd,void *buf,size_t count);
其中,参数的含义如下:
fd
: 要读取的文件描述符(例如打开文件得到的文件描述符)。buf
: 接收读取数据的缓冲区指针,也就是将读取的数据存放到哪里。count
: 要读取的字节数,即期望读取的数据长度。
read()
函数的返回值为实际读取的字节数,如果返回值为-1,则表示读取出错。具体错误可以通过检查 errno变量得到。
使用read()
进行读取操作时,它会尽可地从文件中读取指定数量的字节数据,并将其存入指定的缓冲区中,返回实际读取的字节数。注意,它并不会处理字符串中的null 终止符,而是单纯地按照指定的字节数进行读取。
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#define BUFFER_SIZE 1024
int main() {
int fd;
char buffer[BUFFER_SIZE];
// 打开文件
fd = open("example.txt", O_RDONLY);
if (fd == -1) {
perror("Failed to open file");
exit(1);
}
// 读取文件内容
ssize_t bytesRead = read(fd, buffer, BUFFER_SIZE);
if (bytesRead == -1) {
perror("Failed to read file");
exit(1);
}
printf("Read %zd bytes from file: %.*s\n", bytesRead, (int)bytesRead, buffer);
// 关闭文件
close(fd);
return 0;
}
在上述示例中,我们首先使用 open()
函数打开一个名为"example.txt" 的文件,然后用read()
函数从该文件中读最多 BUFER_SIZE
字节的数据,并将其存在buffer
数组中。输出结果显示实际读取的字节数以及读取的内容。
需要注意的是,read()
函数是一个阻塞函数,如果没有足够的数据可供读取,它将一直等待直到有足够的数据可读或发生错误,如果需要进行非阻塞读取,可以使用 fcntl()
函数设置文件描述符的标志位。
write()
write()
函数是一个系统调用,用于将数据从文件描述符 (file descriptor) 写入到文件或设备中
函数原型如下:
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
- 参数
fd
是文件描述符,指定要写入数的目标文件或设备。 - 参数
buf
是指向要写入数据的缓冲区的指针。 - 参数
count
是要写入的字节数。
write()
函数返回成功写入的字节数,如果出现错误则返回 -1,并设置全局变量 errno
来指示具体的错误信息。
以下是一个简单的示例,演示如何使用 write()
函数将数据写入文件:
#include <unistd.h>
#include <fcntl.h>
int main() {
int fd = open("example.txt", O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
if (fd == -1) {
perror("无法打开文件");
return 1;
}
const char* message = "Hello, World!";
ssize_t bytes_written = write(fd, message, strlen(message));
if (bytes_written == -1) {
perror("写入文件发生错误");
close(fd);
return 1;
}
close(fd);
return 0;
}
在上述示中,我们首先用open()
函数打开一个文件,并进行错误检查。然后,我们定义一个字串 message
,将其作为数据写入文件。我使用write()
函数来执行实际的写入操作,并检查返回值以处理写入错误。最后,我们使用 close()
函数关闭文件描述符。
close()
int close(int fd);
该函数用来关闭一个打开的文件描述符,关闭一个文件时还会释放该进程加在该文件上的所有记录锁。当一个进程终止时,内核将会自动关闭它所有打开的文件。
perror()
perror()
是一个C函数,用于将上一个函数调用发生的错误输出到标准流(stderr)。它可以帮助开发者追踪和调试程序中的错误。
perror()
函数的声明如下:
#include <stdio.h>
void perror(const char *s);
perror()
接受一个参数 s
,它是一个指向以 null 结尾的字符串的指针。通常,s
参数用来提供关于错误的附加信息,以帮助识别具体的错误原因。
perror()
函数会根据全局变量 errno
的值,在标准错误流中打印相应的错误消息。 errno
存储了最近一次函数调用失败时设置的错误码。
以下是一个示例,演示如何使用 perror()
函数打印与文件操作相关的错误消息:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main() {
FILE *file = fopen("nonexistent_file.txt", "r");
if (file == NULL) {
perror("Error");
exit(EXIT_FAILURE);
}
// 文件操作...
fclose(file);
return 0;
}
//输出结果:Error: No such file or directory
在上述示中,fopen()
函数尝试打开一个不存在的文件,并返回 NULL ,表示文打开失败。然后,我们用 perror()
函数打印与此相关的错误消息当程序运行时,它会输出类似以下内容的错误消息:
Error: No such file or directory
通过使用 perror()
函数,我们可以获得有关错误的更详细信息,以便进行适当的处理和调试。
- 请注意,在调用 perror() 之前,必须包含<stdio.h> 和 <stdlib.h> 头文件,并且确保 errno变量已设置为正确的错误码。
strerror()
strerror()
是个在C 语言中的函数,用于将错误码转换为对应的错误信息字符串。它的原型如下:
#include <string.h>
char *strerror(int errnum);
其中,errnum
参数是一个整数,表示错误码
strerror()
函教会根据给定的错误码 errnum
返回对应的错误信息字符串,这些错误信息通定义在系统的错误码库中,每个错误码都有一个相应的错误描述。
以下是一个示例代码,演示了使用 strerror()
函数来获取错误信息字符串的过程:
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main() {
int errnum = 2; // 示例错误码,表示文件或目录不存在
const char *errMsg = strerror(errnum);
printf("Error message for errno %d: %s\n", errnum, errMsg);
return 0;
}
在上述示例中,我们将错码设为2
,对应的错误是“No such fle or directry”
(文件或录不存在)。通过调用 strerror()
函数,我们可以获得这个错误码对应的错误信息字符串,并将其打印输出。
- 需要注意的是,
strerror()
函数返回的错误信息字符串是一个指向静态存储区域的指针,因此不要试图修改或释放它。
lseek()
lseek() 是一个在 Unix/Linux 系统下用于改变文件位置偏移量的系统调用函数。它的原型如下:
include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
其中,参数的含义如下:
fd
: 文件描述符,表示要进行操作的文件offset
: 位移量,表示要进行的位移大小whence
: 位移基准,指定 offset 是相对于哪个位置进行位移。它可以取以下值之一:SEEK_SET
: 将文件位置设置为距离文件开头offset
个字节处。SEEK_CUR
:将文件位置设置为距离当前位置offset
个字节处。SEEK_END
: 将文件位置设置为距离文件未尾offset
个字节处。
lseek()
函数可以用于调整文件的读/写位置。它允许你在文件中任意位置进行读/写操作,而不仅仅是顺序读/写。
以下是一个简单的示例,展示了如何使用 lseek()
函数改变文件位置:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
int main() {
int fd;
off_t offset;
// 打开文件
fd = open("example.txt", O_RDONLY);
if (fd == -1) {
perror("Failed to open file");
exit(1);
}
// 设置文件位置为距离开头 10 个字节处
offset = lseek(fd, 10, SEEK_SET);
if (offset == -1) {
perror("Failed to seek file");
exit(1);
}
printf("New file position: %lld\n", (long long)offset);
// 关闭文件
close(fd);
return 0;
}
在上述例中,我们首先使用open()
函数打开一个名为example.txt
的文件然后用 lseek()
将文件位置设置为距离文件开头 10 字节处。最后,我们输出设置后的文件位置。
- 需要注意的是,
lseek()
函数返回设置后的文件位置,它是相对于文件开头的偏移量,如果成功,函数返回的值将是非负的;如果出错,将返回 -1,并设置相应的错误码。
access()
access()
函数是一个用于检查文件或路径的访问权限的函数,在 Unix/Linux 系统中使用。它的原型如下:
#include <unistd.h>
int access(const char *path, int mode);
其中,参数的含义如下:
path
: 要检查权限的文件或路径mode
: 要检查的访问模式
access()
函教通过将path
参教指定的文件或路径与mode
参数中的访问模式进行比较,来判断是否有相应的权限。访问模式可以是以下值之一 (也可以通过按位或运算符 | 结合多个模式) :F_OK
: 检查文件是否存在R_OK
: 检查读取权限W_OK
: 检查写入权限X_OK
: 检查执行权限
返回值为 0表示具有相应的权限,返回值为 -1 表示没有相应的权限或发生了错误,可以通过 errno
来获取具体的错误信息。
以下是一个简单的示例,展示如何使用 access() 函数检查文件的访问权限:
#include <stdio.h>
#include <unistd.h>
int main() {
const char *path = "example.txt";
// 检查文件是否存在
if (access(path, F_OK) != 0) {
perror("File does not exist");
return 1;
}
// 检查读取权限
if (access(path, R_OK) != 0) {
perror("No read permission");
return 1;
}
// 检查写入权限
if (access(path, W_OK) != 0) {
perror("No write permission");
return 1;
}
// 检查执行权限
if (access(path, X_OK) != 0) {
perror("No execute permission");
return 1;
}
printf("File has all necessary permissions\n");
return 0;
}
在上述示例中,我们通过access()
函数检查名为"example.txt"
的文件是否存在以及是否具有读取、写入和执行权限。如果某个权限不可用,会打印相应的错误信息。
unlink()
unlink()
函数是用于删除文件的函数,在Unix/Linux系统中使用。它的原型如下:
#include <unistd.h>
int unlink(const char *path);
其中,参数的含义如下:
path
: 要删除的文件的路径
unlink ()
函数会删除指定路径下的文件。如果成功删除文件,则返回值为0,如果发生错误,则返回值为 -1,并且可以通过 errno
获取具体的错误信息。
以下是一个简单的示例,展示如何使用unlink ()
函数删除文件:
#include <stdio.h>
#include <unistd.h>
int main() {
const char *path = "example.txt";
// 删除文件
if (unlink(path) == -1) {
perror("Failed to delete file");
return 1;
}
printf("File deleted successfully\n");
return 0;
}
在上述示例中,我们使用 unlink()
函数删除名“exampletxt"
的文件,如果删除文件失败,将打的相应的错误信息; 如果成功删除文件,打印"File deleted successfully"
需要注意的是,一旦使用unlink()
函数删除文件,文件将无法恢复。因此,在调用unlink()
函数之前,请确保真正想要删除该文件。
dup()
dup()
是一个在 Unix/Linux 系统下用于复制文件描述符的系统调用函数。它的原型如下:
#include <unistd.h>
int dup(int oldfd);
其中,参数的含义如下:
oldfd
: 需要被复制的文件描述符。
dup()
函数用于复制文件描述符,并返回复制后的新文件描述符。新的文件描述符将指向与原给描述符相同的文件表项,这意味着两个文件描述符将共享文件偏移量和文件状态标志。
以下是一个简单的示例,展示了如何使用dup()
函数复制文件描述符:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
int main() {
int fd, newfd;
// 打开文件
fd = open("example.txt", O_RDONLY);
if (fd == -1) {
perror("Failed to open file");
exit(1);
}
// 复制文件描述符
newfd = dup(fd);
if (newfd == -1) {
perror("Failed to duplicate file descriptor");
exit(1);
}
printf("Original file descriptor: %d\n", fd);
printf("Newly duplicated file descriptor: %d\n", newfd);
// 关闭文件描述符
close(fd);
close(newfd);
return 0;
}
//Original file descriptor: 3
//Newly duplicated file descriptor: 4
在上述示例中,我们首先使用 open()
函数打开一个名为example.txt
的文件,并获 取现返回的文件描述符 fd
,然后,我们使用dup()
函数复制文件描述符 fd
,并将复制后的新文件描述符 newfd
存储起来。最后,我们输出原始文件描述符和复制后的新文件描述符。
需要注意的是,du()
函数返回一个新的文件描述符,如果成功,则为最小可用的未使用文件描述符,如果出错,则返回 -1,并设置相应的错误码。
dup2()
dup2()
函数是在 Unix/Linux 系统下用于复制文件描述符的系统调用函数。它的原型如下:
#include <unistd.h>
int dup2(int oldfd, int newfd):
其中,参数的含义如下
oldfd
: 需要被复制的文件描述符newfd
: 新的文件描述符,如果该文件描述符已经打开,则会先被关闭。
dup2()
函数用于复制文件描述符,并将复制后的描述符与指定的新描述符绑定。如果新描述符 newfd
已经打开,则会先将其关闭,然后再进行复制,以下是一个简单的示例,展示了如何使用 dup2() 函数复制文件描述符;
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
int main() {
int fd, newfd;
// 打开文件
fd = open("example.txt", O_RDONLY);
if (fd == -1) {
perror("Failed to open file");
exit(1);
}
// 复制文件描述符到新的描述符
newfd = dup2(fd, 10);
if (newfd == -1) {
perror("Failed to duplicate file descriptor");
exit(1);
}
printf("Original file descriptor: %d\n", fd);
printf("Duplicated file descriptor: %d\n", newfd);
// 关闭文件描述符
close(fd);
close(newfd);
return 0;
}
//Original file descriptor: 3
//Duplicated file descriptor: 10
在上述示例中,我们首先使用 open()
函数打开一个名为“example.txt"
的文件,并获取返回的文件描述符 fd
。然后,我们使用 dup2()
函数将文件描述符 fd
复制到新的描述符 10上,并将复制后的新文件描述符 newfd
存储起来。最后,我们输出原始文件描述符和复制后的新文件描述符。
需要注意的是,dup2()
函数返一个新的文件描述符,如果复制成功,则为指定的新描述符,如果出错,则返回-1,并设置相应的错误码。
例子2
当使用 dup2()
函数时,可以将一个文件描述符复制到另一个预先打开的、未被占用的文件描述符上以下是另一个示例,展示如何将标准输出重定向到一个文件中:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
int main() {
int fd, newfd;
// 打开文件
fd = open("output.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fd == -1) {
perror("Failed to open file");
exit(1);
}
// 将标准输出重定向到文件
newfd = dup2(fd, 1);
if (newfd == -1) {
perror("Failed to duplicate file descriptor");
exit(1);
}
// 输出到标准输出,实际上将会写入文件
printf("This message will be written to the file.\n");
// 关闭文件描述符
close(fd);
return 0;
}
在上述示例中,我们首先用 open()
函打开一个名为"output.txt"
的文件,并获返回的文件描述符fd
。然后,我使用 dup2()
函将文件描符 fd
复制到标准输出的描述符 1
上,从而将标准输出重定向到文件。现在,任何输出到标准输出的内容都将被写入到文件“output.txt"
中。
需要注意的是,我们在 open()
函数中用了 O_WRONLY | O_CREAT | O_TRUNC参数,这表示以只写方式打开文件,如文不存在则创建文件,如果文件已存在则将其截断为空文件。另外,0644 是指定新创建的文件的权限,其中0
表示八进制。
stat()
stat()
是一个用于获取文件或文件系统相关信息的函数,在 Unix/Linux 系统中广泛使用。它的原型如下:
#include <sys/types .h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *path, struct stat *buf);
其中,参数的含义如下:
path
: 要获取信息的文件或文件夹路径buf
: 用于存储获取到的文件信息的结构体指针。
stat()
函数会根据指定的路径 path
获取文件的元数据信息,并将结果存储在 struct_stat
结构体中。这个结构体定义如下。
struct stat {
dev_t st_dev; /* 文件的设备 ID */
ino_t st_ino; /* inode 号 */
mode_t st_mode; /* 文件的类型和权限 */
nlink_t st_nlink; /* 链接数 */
uid_t st_uid; /* 文件所属用户的 ID */
gid_t st_gid; /* 文件所属组的 ID */
dev_t st_rdev; /* 设备号(如果是设备文件) */
off_t st_size; /* 文件大小(字节数) */
blksize_t st_blksize; /* I/O 块大小 */
blkcnt_t st_blocks; /* 分配的块数量 */
time_t st_atime; /* 最后访问时间 */
time_t st_mtime; /* 最后修改时间 */
time_t st_ctime; /* 文件状态更改时间 */
};
通过 stat()
函数获取到的文件信息包括文件类型和访问权限、用户 ID 和组 ID、文件大小、最后访问、修改和状态更改时间等。
以下是一个简单的示例,展示如何使用stat()
函数获取文件的信息:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
int main() {
const char *path = "example.txt";
struct stat file_info;
// 获取文件信息
if (stat(path, &file_info) == -1) {
perror("Failed to get file information");
exit(1);
}
// 打印文件大小
printf("File size: %lld bytes\n", (long long)file_info.st_size);
// 打印最后修改时间
printf("Last modified time: %s", ctime(&file_info.st_mtime));
return 0;
}
在上述示例中,我们使用 stat()
函数获取名为"example.txt 的文件的信息,并将结果存储在 file_info
结构体中。然后,我们打了文件的大小和最后修改时间。
- 请注意,
file_info.st_size
是文件的大小(以字节为单位),file_info.st_mtime
是最后修改时间(表示为时间戳)。为了将时间转换为可读格式,我们使用了ctime()
函教。
fstat()
fstat()
函数是一个用于获取已打开文件相关信息的函数,在 Unix/Linux 系统中使用。它的原型如下:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int fstat(int fd, struct stat *buf);
其中,参数的含义如下
fd
: 已打开文件的文件描述符。buf
: 用于存储获取到的文件信息的结构体指针。
fstat()
函数会根给定的文件描述符fd
获取文件的元数据信息,并将结果存储在struct stat
结构体中,它的结构体定义与stat()
函数中的相同。
以下是一个简单的示例,展示如何使用 fstat()
函数获取已打开文件的信息:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main() {
int fd;
struct stat file_info;
// 打开文件
fd = open("example.txt", O_RDONLY);
if (fd == -1) {
perror("Failed to open file");
exit(1);
}
// 获取文件信息
if (fstat(fd, &file_info) == -1) {
perror("Failed to get file information");
exit(1);
}
// 打印文件大小
printf("File size: %lld bytes\n", (long long)file_info.st_size);
// 打印最后修改时间
printf("Last modified time: %s", ctime(&file_info.st_mtime));
// 关闭文件
close(fd);
return 0;
}
在上述示例中,我们首先使用 open()
打开名为example.txt
的文件,并获取文件描术符 fd
。然后,我使用 fstat()
欧数获该文件的信息,并将结果存储在file_info
结构体中。最后,我们打印文件的大小和最后修改时间。
- 请注意,与
stat()
函数不同的是,fstat()
函数需要传入一个已打开文件的文件描述符而不是文件路径。
rename()
rename()
函数用于重命名文件或将文件移动到新位置。在C语言中,rename()
函数的原型如下:
#include <stdio.h>
int rename(const char *oldpath, const char *newpath);
其中,参数的含义如下:
oldpath
: 旧文件路径,即要重命名或移动的文件的当前路径newpath
: 新文件路径,即要重命名或移动的文件的目标路径。rename()
函数将文件oldpath
重命名为newpath
或者将文件oldpath
移动到newpath
,如果操功,函数返回0;如果发生错误,区数返回-1,并且可以使errno
获取具体的错误信息。
以下是一个示例,展示如何使用 rename()
函数重命名文件或将文件移动到新位置:
#include <stdio.h>
int main() {
const char *oldpath = "oldname.txt";
const char *newpath = "newname.txt";
// 重命名文件
if (rename(oldpath, newpath) == -1) {
perror("Failed to rename file");
return 1;
}
printf("File renamed successfully\n");
return 0;
}
在上述示例中,我们使用rename()
函数将名为"oldname.txt
的文件重命名为"newname.txt",如果重命名成功,将印"File renamed successfuly";
如果失败,将打印相应的错误信息。
- 需要注意的是,
rename()
函数也可以用于将文件移动到不同的目录,只需在newpath
参数中给出新的路径即可。