文件写入¶
通过 文件读取 一节,相信读者已经掌握了通过 系统调用 读取文件内容的方法。 本节,我们将更近一步,学习如何将数据写入文件。
同样,我们还是通过实现一个简单的写文件程序 write 来学习相关 系统调用 的使用方法。 write 程序用法如下:
$ ./write first_file.txt 'Hello, world!'
Bytes written: 13
程序接收两个命令行参数—— 待写入文件路径 以及 写入内容 (字符串)。 程序负责打开待写入文件并写入指定内容,最后提示成功写入字节数。
程序源码 write.c 如下:
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 | #include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
// check cmdline arguments
if (argc != 3) {
fprintf(stderr, "Bad arguments!");
return 1;
}
char *pathname = argv[1];
char *data = argv[2];
// open file
int fd = open(pathname, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);
if (fd == -1) {
perror("Can not open file");
return 2;
}
// write data
int bytes_written = write(fd, data, strlen(data));
if (bytes_written == -1) {
perror("Can not write file");
return 3;
}
// prompt bytes written
printf("Bytes written: %d\n", bytes_written);
// close file
close(fd);
return 0;
}
|
第 9-12 行,检查 命令行参数 是否符合预期。
第 18-22 行,调用 open 系统调用,打开待写入文件。 open 系统调用需要 3 个参数: 文件路径 ( pathname )、 标志位 ( flags )以及 模式位 ( mode )。
标志位 影响打开文件行为,例子中指定了 3 个标志:
- O_WRONLY ,表示 只写打开
- O_CREAT ,表示文件不存在时 创建文件
- O_TRUNC ,表示文件存在时 清空文件
模式位 指定创建文件权限,仅当 O_CREAT 指定时有效。 例子指定了 所属用户 对创建后的文件拥有 读写权限 :
- S_IRUSR , 所属用户 拥有 读权限
- S_IWUSR , 所属用户 拥有 写权限
第 25-29 行,调用 write 系统调用将数据写入文件。 同样, write 系统调用需要 3 个参数: 文件描述符 ( fd )、 数据缓冲区地址 ( buf ) 以及 数据字节数 ( count )。 write 系统调用执行成功时,返回 成功写入字节数 ;出错则返回 -1 。
接下来,我们运行 make 命令编译并执行 write 程序:
$ make
gcc -c -o write.o write.c
gcc -o write write.o
./write first_file.txt 'Hello, world!'
Bytes written: 13
$ cat first_file.txt
Hello, world!%
注意到, make 命令运行 write 程序往 first_file.txt 这个文件写入了一个字符串 Hello, world!
,
这个行为是在 Makefile 中定义的。
另外, cat 命令输出的内容末尾带着 %
符号,这代表没有换行符( new line ),即 \n
。
检查新创建文件 first_file.txt 的权限,确实是 所属用户可读可写 ( rw ):
$ ls -l first_file.txt
-rw------- 1 fasion fasion 3 Jul 17 09:15 first_file.txt
接着,再次运行 write 往 first_file.txt 文件写入字符串 abc
:
$ $ ./write first_file.txt abc
Bytes written: 3
$ cat first_file.txt
abc%
再次写入时,行为与 open 系统调用的 flags 参数相关:
O_TRUNC
表示当目标文件存在时,清空文件。
如果不使用该标志,那么文件内容应该是 abclo, world!
(从头覆写)。
相反,如果使用 O_APPEND
标志,那么文件内容则是 Hello, world!abc
(末尾追加)。