文件写入

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

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

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

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

程序源码 write.c 如下:

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

接着,再次运行 writefirst_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 (末尾追加)。

下一步

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

../../_images/wechat-mp-qrcode.png

小菜学编程