在Linux系统编程中,文件IO操作是非常常见和重要的操作之一。通过文件IO操作,我们可以打开、读取、写入和关闭文件,对文件进行定位、复制、删除和重命名等操作。本篇博客将介绍一些常用的文件IO操作函数。
1. open()
1.1 原型、参数及返回值说明
1.1.1 原型:
open()函数是Linux系统编程中常用的文件IO操作函数之一。它用于打开文件并返回一个文件描述符,以便后续的文件读写操作。
open()函数的原型如下:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags, mode_t mode);
1.1.2 参数说明:
-
pathname
:要打开的文件路径名。 -
flags
:打开文件的模式标志,可以是以下几种模式的组合:-
O_RDONLY
:只读模式打开文件。 -
O_WRONLY
:只写模式打开文件。 -
O_RDWR
:读写模式打开文件。 -
O_CREAT
:如果文件不存在,则创建文件。 -
O_EXCL
:与O_CREAT一同使用,如果文件已存在,则返回错误。 -
O_TRUNC
:如果文件存在且以可写模式打开,则将文件截断为0。 -
O_APPEND
:在文件末尾追加数据。
-
-
mode
: 创建文件时的访问权限,只有在使用O_CREAT时才有效。
可以使用如下几个宏来设置权限:- S_IRUSR:用户读权限。
- S_IWUSR:用户写权限。
- S_IXUSR:用户执行权限。
- S_IRGRP:组读权限。
- S_IWGRP:组写权限。
- S_IXGRP:组执行权限。
- S_IROTH:其他用户读权限。
- S_IWOTH:其他用户写权限。
- S_IXOTH:其他用户执行权限。
1.1.3 返回值:
- 成功:返回一个非负整数的文件描述符,用于后续的文件IO操作。
- 失败:返回-1,并设置errno变量来指示错误类型。
1.2 函数示例
下面是一个使用open()函数的示例:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
int main() {
int fd;
// 打开文件
fd = open("example.txt", O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
if (fd == -1) {
perror("open");
return errno;
}
// 写入数据
char buffer[] = "Hello, world!";
ssize_t ret = write(fd, buffer, sizeof(buffer) - 1);
if (ret == -1) {
perror("write");
close(fd);
return errno;
}
// 关闭文件
close(fd);
return 0;
}
1.3 代码解释
在上述示例中,我们首先使用open()函数以只写模式打开一个文件example.txt。如果文件不存在,则创建该文件,并设置访问权限为用户可读可写。如果打开文件失败,我们使用perror()函数打印错误信息,并返回errno变量。
接下来,我们使用write()函数向文件中写入数据。在本例中,我们写入了字符串"Hello, world!"。如果写入数据失败,我们同样使用perror()函数打印错误信息,并在关闭文件前返回errno变量。
最后,我们使用close()函数关闭文件。
2. close()
2.1 原型、参数及返回值说明
2.1.1 原型:
close()函数是Linux系统编程中用于关闭文件的函数。它接受一个文件描述符作为参数,并返回一个整数值来指示操作是否成功。
close()函数的原型如下:
#include <unistd.h>
int close(int fd);
2.1.2 参数:
-
fd
:要关闭的文件描述符。
2.1.3 返回值:
- 成功:返回0。
-
失败:返回-1,并设置
errno
变量来指示错误类型。
2.2 函数示例
下面是一个使用close()函数的示例:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
int main() {
int fd;
// 打开文件
fd = open("example.txt", O_RDONLY);
if (fd == -1) {
perror("open");
return errno;
}
// 关闭文件
int ret = close(fd);
if (ret == -1) {
perror("close");
return errno;
}
return 0;
}
2.3 代码解释
在上述示例中,我们首先使用open()
函数以只读模式打开一个文件example.txt
,并将返回的文件描述符存储在变量fd
中。如果打开文件失败,我们使用perror()
函数打印错误信息,并返回errno
变量。
接下来,我们使用close()
函数关闭文件。如果关闭文件失败,我们同样使用perror()
函数打印错误信息,并返回errno
变量。
需要注意的是,关闭文件后,我们不应再对该文件描述符进行任何操作。
3. read()
3.1 原型、参数及返回值说明
3.1.1 原型:
read()函数是Linux系统编程中用于从文件中读取数据的函数。它接受一个文件描述符、一个缓冲区地址和一个读取的最大字节数作为参数,并返回实际读取的字节数。
read()函数的原型如下:
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
3.1.2 参数:
-
fd
:要读取的文件的文件描述符。 -
buf
:用于存储读取数据的缓冲区的地址。 -
count
:要读取的最大字节数。
3.1.3 返回值:
- 成功:返回实际读取的字节数。
-
失败:返回
-1
,并设置errno
变量来指示错误类型。
3.2 函数示例
下面是一个使用read()函数的示例:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
int main() {
int fd;
// 打开文件
fd = open("example.txt", O_RDONLY);
if (fd == -1) {
perror("open");
return errno;
}
// 读取数据
char buffer[100];
ssize_t ret = read(fd, buffer, sizeof(buffer));
if (ret == -1) {
perror("read");
close(fd);
return errno;
}
// 输出读取的数据
printf("Read %ld bytes: %s\n", ret, buffer);
// 关闭文件
close(fd);
return 0;
}
3.3 代码解释
在上述示例中,我们首先使用open()
函数以只读模式打开一个文件example.txt
,并将返回的文件描述符存储在变量fd
中。如果打开文件失败,我们使用perror()
函数打印错误信息,并返回errno
变量。
接下来,我们使用read()
函数从文件中读取数据。我们定义一个长度为100的缓冲区buffer
,并将其作为参数传递给read()
函数。read()
函数将尽量读取count
个字节的数据,并将其存储在缓冲区中。如果读取数据失败,我们同样使用perror()
函数打印错误信息,并在关闭文件前返回errno
变量。
最后,我们使用printf()
函数输出读取的数据,并使用close()
函数关闭文件。
需要注意的是,read()函数是一个阻塞函数,如果文件中没有足够的数据可读,它将一直等待直到有足够的数据可读或者发生错误。如果需要非阻塞地读取数据,可以使用fcntl()函数设置文件描述符为非阻塞模式。
4. write()
4.1 原型、参数及返回值说明
4.1.1 原型:
write()函数是Linux系统编程中用于向文件中写入数据的函数。它接受一个文件描述符、一个数据缓冲区地址和要写入的字节数作为参数,并返回实际写入的字节数。
write()函数的原型如下:
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
4.1.2 参数:
-
fd
:要写入的文件的文件描述符。 -
buf
:要写入的数据的缓冲区的地址。 -
count
:要写入的字节数。
4.1.3 返回值:
- 成功:返回实际写入的字节数。
-
失败:返回
-1
,并设置errno
变量来指示错误类型。
4.2 函数示例
下面是一个使用write()函数的示例:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
int main() {
int fd;
// 打开文件
fd = open("example.txt", O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
if (fd == -1) {
perror("open");
return errno;
}
// 写入数据
char buffer[] = "Hello, World!";
ssize_t ret = write(fd, buffer, sizeof(buffer) - 1);
if (ret == -1) {
perror("write");
close(fd);
return errno;
}
// 关闭文件
close(fd);
return 0;
}
4.3 代码解释
在上述示例中,我们首先使用open()
函数以只写模式打开一个文件example.txt
,并将返回的文件描述符存储在变量fd
中。如果打开文件失败,我们使用perror()
函数打印错误信息,并返回errno
变量。
接下来,我们使用write()
函数将数据写入文件中。我们定义一个字符串buffer
,并将其作为参数传递给write()
函数。write()
函数将尽量写入count
个字节的数据到文件中。如果写入数据失败,我们同样使用perror()
函数打印错误信息,并在关闭文件前返回errno
变量。
最后,我们使用close()
函数关闭文件。
需要注意的是,write()函数是一个阻塞函数,如果文件无法立即接受写入的数据(例如,磁盘空间不足),它将一直等待直到可以写入数据或者发生错误。如果需要非阻塞地写入数据,可以使用fcntl()函数设置文件描述符为非阻塞模式。
5. lseek()
5.1 原型、参数及返回值说明
5.1.1 原型:
lseek()函数是Linux系统编程中用于在文件中定位读写位置的函数。它接受一个文件描述符、一个偏移量和一个起始位置作为参数,并返回新的读写位置。
lseek()函数的原型如下:
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
5.1.2 参数:
-
fd
:要定位的文件的文件描述符。 -
offset
:偏移量,可以是正数、负数或零。 -
whence
:起始位置,可以取以下三个值:-
SEEK_SET
:从文件开头开始计算偏移量。 -
SEEK_CUR
:从当前读写位置开始计算偏移量。 -
SEEK_END
:从文件末尾开始计算偏移量。
-
5.1.3 返回值:
- 成功:返回新的读写位置。
-
失败:返回
-1
,并设置errno
变量来指示错误类型。
5.2 函数示例
下面是一个使用lseek()函数的示例:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
int main() {
int fd;
// 打开文件
fd = open("example.txt", O_RDONLY);
if (fd == -1) {
perror("open");
return errno;
}
// 定位读写位置
off_t ret = lseek(fd, 5, SEEK_SET);
if (ret == -1) {
perror("lseek");
close(fd);
return errno;
}
// 读取数据
char buffer[10];
ssize_t n = read(fd, buffer, sizeof(buffer) - 1);
if (n == -1) {
perror("read");
close(fd);
return errno;
}
buffer[n] = '\0';
printf("Data: %s\n", buffer);
// 关闭文件
close(fd);
return 0;
}
5.3 代码解释
在上述示例中,我们首先使用open()
函数以只读模式打开一个文件example.txt
,并将返回的文件描述符存储在变量fd
中。如果打开文件失败,我们使用perror()
函数打印错误信息,并返回errno
变量。
接下来,我们使用lseek()
函数将读写位置定位到文件开头后的第5个字节。我们将文件描述符、偏移量和起始位置作为参数传递给lseek()
函数。如果定位读写位置失败,我们同样使用perror()
函数打印错误信息,并在关闭文件前返回errno
变量。
然后,我们使用read()
函数从文件中读取数据。我们定义一个缓冲区buffer
,并将其作为参数传递给read()
函数。read()
函数将尽量读取count
个字节的数据到缓冲区中。如果读取数据失败,我们同样使用perror()
函数打印错误信息,并在关闭文件前返回errno
变量。最后,我们在缓冲区末尾添加一个空字符,并使用printf()
函数打印读取到的数据。
最后,我们使用close()
函数关闭文件。
需要注意的是,lseek()函数可以用于定位读写位置,但并不会改变文件的大小。如果需要改变文件的大小,可以使用truncate()函数或ftruncate()函数。
6. stat()
6.1 原型、参数及返回值说明
6.1.1 原型:
stat()函数是Linux系统编程中用于获取文件信息的函数。它接受一个文件路径作为参数,并返回一个包含文件信息的结构体。
stat()函数的原型如下:
#include <sys/types.h>
#include <sys/stat.h>
int stat(const char *pathname, struct stat *buf);
6.1.2 参数:
-
pathname
:要获取信息的文件路径。 -
buf
:用于存储文件信息的结构体指针。
6.1.3 返回值:
- 成功:返回0。
-
失败:返回
-1
,并设置errno
变量来指示错误类型。
struct stat
结构体包含了文件的各种信息,包括文件类型、权限、大小、创建时间、修改时间等。
下面是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; // 如果文件是设备文件,则为设备的ID
off_t st_size; // 文件的大小(字节)
blksize_t st_blksize; // 文件系统的块大小
blkcnt_t st_blocks; // 分配给文件的块数
time_t st_atime; // 文件的最后访问时间
time_t st_mtime; // 文件的最后修改时间
time_t st_ctime; // 文件的最后状态改变时间
};
6.2 函数示例
下面是一个使用stat()函数的示例:
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <errno.h>
int main() {
const char *pathname = "example.txt";
struct stat file_info;
// 获取文件信息
int ret = stat(pathname, &file_info);
if (ret == -1) {
perror("stat");
return errno;
}
// 打印文件信息
printf("File Size: %ld bytes\n", file_info.st_size);
printf("File Permissions: %o\n", file_info.st_mode & 0777);
printf("File Owner UID: %d\n", file_info.st_uid);
printf("File Owner GID: %d\n", file_info.st_gid);
return 0;
}
6.3 代码解释
在上述示例中,我们首先定义了一个文件路径pathname
和一个struct stat
结构体file_info
,用于存储获取到的文件信息。
然后,我们使用stat()
函数将文件信息存储到file_info
结构体中。我们将文件路径和file_info
结构体指针作为参数传递给stat()
函数。如果获取文件信息失败,我们使用perror()
函数打印错误信息,并返回errno
变量。
最后,我们使用printf()
函数打印获取到的文件信息,包括文件大小、文件权限、文件所有者的UID
和GID
等。
需要注意的是,stat()函数只能获取文件的信息,而不能修改文件的信息。如果需要修改文件的信息,可以使用chmod()函数来修改文件的权限。
7. fcntl()
7.1 原型、参数及返回值说明
7.1.1 原型:
fcntl()函数是Linux系统编程中用于对文件描述符进行控制操作的函数。它可以用于设置文件状态标志、获取文件状态标志、设置文件锁等。
fcntl()函数的原型如下:
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );
7.1.2 参数:
-
fd
:文件描述符,可以是打开文件的文件描述符,也可以是套接字的文件描述符。 -
cmd
:控制命令,用于指定要执行的操作。 -
arg
:可选参数,用于传递特定操作的参数。
7.1.3 返回值:
- 成功:根据不同的操作命令返回不同的值,一般为0或一个正整数。
-
失败:返回
-1
,并设置errno
变量来指示错误类型。
下面是fcntl()函数的一些常用命令:
-
F_DUPFD
:复制文件描述符,创建一个新的文件描述符,该描述符与原始描述符指向相同的打开文件。 -
F_GETFD
:获取文件描述符的文件状态标志。 -
F_SETFD
:设置文件描述符的文件状态标志。 -
F_GETFL
:获取文件的打开方式和状态标志。 -
F_SETFL
:设置文件的打开方式和状态标志。 -
F_GETLK
:获取文件锁的信息。 -
F_SETLK
:设置文件锁。 -
F_SETLKW
:设置文件锁,如果无法获取锁,则阻塞等待。
7.2 函数示例
下面是一个使用fcntl()函数的示例:
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
int main() {
int fd = open("example.txt", O_RDWR);
if (fd == -1) {
perror("open");
return errno;
}
// 获取文件的打开方式和状态标志
int flags = fcntl(fd, F_GETFL);
if (flags == -1) {
perror("fcntl");
return errno;
}
// 设置文件的状态标志为非阻塞
flags |= O_NONBLOCK;
int ret = fcntl(fd, F_SETFL, flags);
if (ret == -1) {
perror("fcntl");
return errno;
}
// 关闭文件描述符
close(fd);
return 0;
}
7.3 代码解释
在上述示例中,我们首先使用open()
函数打开一个文件,并将返回的文件描述符存储在变量fd中。如果打开文件失败,我们使用perror()
函数打印错误信息,并返回errno
变量。
然后,我们使用fcntl()
函数获取文件的打开方式和状态标志。将文件描述符和F_GETFL
命令作为参数传递给fcntl()
函数,获取到的文件状态标志存储在变量flags
中。如果获取文件状态标志失败,我们同样使用perror()
函数打印错误信息,并返回errno
变量。
接下来,我们将文件的状态标志设置为非阻塞,通过将O_NONBLOCK
标志位与flags
进行按位或操作。然后,我们使用fcntl()
函数将修改后的状态标志设置回文件描述符。将文件描述符、F_SETFL
命令和修改后的状态标志作为参数传递给fcntl()
函数。如果设置文件状态标志失败,我们同样使用perror()
函数打印错误信息,并返回errno
变量。
最后,我们使用close()
函数关闭文件描述符,释放资源。
需要注意的是,fcntl()函数的使用非常灵活,可以根据需要进行各种操作,如复制文件描述符、获取文件锁等。在使用fcntl()函数时,需要注意错误处理,并确保文件描述符的有效性。同时,需要在不再需要使用文件描述符时及时关闭文件描述符,以释放资源并避免资源泄漏。
总结
文件IO操作是Linux系统编程中的重要部分。通过open()
、close()
、read()
、write()
等函数,我们可以对文件进行打开、读取和写入操作。通过lseek()
函数,我们可以在文件中进行定位。而通过stat()
、fcntl()
、dup()
等函数,我们可以获取文件的状态信息,对文件描述符进行控制操作,复制文件描述符等。文章来源:https://www.toymoban.com/news/detail-651710.html
除了上述的函数,还有许多其他的函数可以用于文件IO操作,如mkdir()
用于创建目录,rmdir()
用于删除目录,unlink()
用于删除文件,rename()
用于重命名文件等。文章来源地址https://www.toymoban.com/news/detail-651710.html
到了这里,关于【Linux操作系统】举例解释Linux系统编程中文件io常用的函数的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!