「Linux 系统编程」read 和 write 函数基本使用方法

1 read 函数

1.1 read 函数原型

read 函数所需头文件:

1
#include <unistd.h>

read 函数原型:

1
ssize_t read(int fd, void *buf, size_t count);
  • fd文件描述符。由 open 函数返回,代表打开的文件。
  • buf指向缓冲区的指针。用于存储读取的数据。
  • count:请求数据的 字节数

1.2 read 函数返回值

  • 成功:返回 实际读取的字节数(可能小于请求的字节数)

  • 到达文件末尾:返回 0

  • 失败:返回 -1。此时可通过 perror 函数打印错误信息,或者通过 strerror(errno) 打印 errno 对应的字符串。


1.3 read 函数使用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>

int main() {
int fd = open("marisa.txt", O_RDONLY);
if (fd == -1) {
perror("open");
return 1;
}

char buffer[256];
// 请求字节数为缓冲区大小 - 1 主要是为了安全加上结束字符 \0
ssize_t bytes_read = read(fd, buffer, sizeof(buffer) - 1);

if (bytes_read == -1) {
perror("read");
close(fd);
return 1;
}

buffer[bytes_read] = '\0'; // 添加字符串结束符
printf("Read %zd bytes: %s\n", bytes_read, buffer);

close(fd);

return 0;
}



2 write 函数

2.1 write 函数原型

write 函数所需头文件:

1
#include <unistd.h>

write 函数原型:

1
ssize_t write(int fd, const void *buf, size_t count);
  • fd文件描述符。由 open 函数返回,代表打开的文件。
  • buf指向要写入的数据的缓冲区的指针
  • count:写入数据的 字节数

2.2 write 函数返回值

  • 成功:返回 实际写入的字节数(可能小于请求的字节数)

  • 失败:返回 -1。此时可通过 perror 函数打印错误信息,或者通过 strerror(errno) 打印 errno 对应的字符串。


2.3 write 函数使用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>

int main() {
// 以只写方式创建一个新文件,如果文件存在,则先清空
int fd = open("marisa.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fd == -1) {
perror("open");
return 1;
}

char *str = "This is Scarlet Police.\n";
ssize_t bytes_written = write(fd, str, strlen(str));

if (bytes_written == -1) {
perror("write");
close(fd);
return 1;
}

printf("Written %zd bytes\n", bytes_written);

close(fd);

return 0;
}



3 read 和 write 实现复制文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>

#define BUFFER_SIZE 1024

int main(int argc, char *argv){
if(argc != 3){
// 参数个数必须是 3 个,程序本身、复制源文件、复制目标文件
fprintf(stderr, "Usage: ./%s src_file des_file\n", argv[0]);
return 1;
}

int src_fd = open(argv[1], O_RDONLY);
if(src_fd == -1){
perror("open src");
return 1;
}

int des_fd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0644);
if(des_fd == -1){
perror("open des");
close(src_fd);
return 1;
}

char buffer[BUFFER_SIZE];
ssize_t bytes_read;
// 从 src_file 读取数据并写入数据到 des_file
while((bytes_read = read(src_fd, buffer, BUFFER_SIZE)) > 0){
ssize_t bytes_written = write(des_fd, buffer, bytes_read);
if(bytes_written != bytes_read){
perror("write");
close(src_fd);
close(des_fd);
return 1;
}
}

if(bytes_read == -1){
perror("read");
}

close(src_fd);
close(des_fd);

return 0;
}



4 read / write 和 fgetc / fputc 对比

fgetc/fputc 操作的标准 I/O 流(FILE*)通常关联着一个 用户级缓冲区。这个缓冲区的默认大小通常是 4096 或 8192 字节,但它是可配置的。

所以并不是一个字节一个字节地写。其采用了一种 预读入,缓输出 的机制:

在实际编程中,通常推荐使用 C 标准库函数 fgetc/fputc,除非有特殊需求需要直接使用系统调用函数 read/write(如需要 非阻塞I/O特殊文件操作 等)。标准库函数 提供了更好的 可移植性和易用性,同时在性能上 通过缓冲机制进行了优化


「Linux 系统编程」read 和 write 函数基本使用方法
https://marisamagic.github.io/2025/08/22/20250822/
作者
MarisaMagic
发布于
2025年8月22日
许可协议