文件写入

通过 文件读取 一节,相信读者已经掌握了通过 系统调用 读取文件内容的方法。本节,我们将更近一步,学习如何将数据写入文件。

同样,我们还是通过实现一个简单的写文件程序 write 来学习相关 系统调用 的使用方法。write 程序用法如下:

  1. $ ./write first_file.txt 'Hello, world!'
  2. Bytes written: 13

程序接收两个命令行参数—— 待写入文件路径 以及 写入内容 (字符串)。程序负责打开待写入文件并写入指定内容,最后提示成功写入字节数。

程序源码 write.c 如下:

write.c

  1. #include <fcntl.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5. int main(int argc, char *argv[])
  6. {
  7. // check cmdline arguments
  8. if (argc != 3) {
  9. fprintf(stderr, "Bad arguments!");
  10. return 1;
  11. }
  12. char *pathname = argv[1];
  13. char *data = argv[2];
  14. // open file
  15. int fd = open(pathname, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);
  16. if (fd == -1) {
  17. perror("Can not open file");
  18. return 2;
  19. }
  20. // write data
  21. int bytes_written = write(fd, data, strlen(data));
  22. if (bytes_written == -1) {
  23. perror("Can not write file");
  24. return 3;
  25. }
  26. // prompt bytes written
  27. printf("Bytes written: %d\n", bytes_written);
  28. // close file
  29. close(fd);
  30. return 0;
  31. }

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 程序:

  1. $ make
  2. gcc -c -o write.o write.c
  3. gcc -o write write.o
  4. ./write first_file.txt 'Hello, world!'
  5. Bytes written: 13
  6. $ cat first_file.txt
  7. Hello, world!%

注意到, make 命令运行 write 程序往 first_file.txt 这个文件写入了一个字符串 Hello, world! ,这个行为是在 Makefile 中定义的。另外, cat 命令输出的内容末尾带着 % 符号,这代表没有换行符( new line ),即 \n

检查新创建文件 first_file.txt 的权限,确实是 所属用户可读可写 ( rw ):

  1. $ ls -l first_file.txt
  2. -rw------- 1 fasion fasion 3 Jul 17 09:15 first_file.txt

接着,再次运行 writefirst_file.txt 文件写入字符串 abc

  1. $ $ ./write first_file.txt abc
  2. Bytes written: 3
  3. $ cat first_file.txt
  4. abc%

再次写入时,行为与 open 系统调用的 flags 参数相关:O_TRUNC 表示当目标文件存在时,清空文件。如果不使用该标志,那么文件内容应该是 abclo, world! (从头覆写)。相反,如果使用 O_APPEND 标志,那么文件内容则是 Hello, world!abc (末尾追加)。

下一步

订阅更新,获取更多学习资料,请关注我们的 微信公众号

../../_images/wechat-mp-qrcode.png小菜学编程

参考文献