第20章 read() / write() 関数

目次

20.1. 文字列をヒープにコピー

 read() / write() 関数はファイル記述子を使う場合に使うことができます。

 dprintf も使うことができますが read() / write() 関数の方が見る機会は多いでしょうね。

#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);

 read() 関数の第一引数 fd は読み込み元のファイル記述子、第二引数 buf は読み込んだ中身を保存するバッファー、第三引数の count は読みこみたいバイト数となります。

#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);

 write() 関数の引数は read 関数と同じですね。

 違いは read() が読み込みするのに対して write() は buf の内容を fd (ファイル記述子)に書き込みするぐらいです。

  1 #include <unistd.h>
  2 #include <fcntl.h>
  3 #include <stdio.h>
  4 #include <stdlib.h>
  5
  6 #define BUFFER_SIZE 8192
  7
  8 int main(int argc, char **argv)
  9 {
 10   char buf[BUFFER_SIZE];
 11   int size;
 12   int fd;
 13
 14   if(argc != 2){
 15     fprintf(stderr,"ファイル名を指定してください\n");
 16     exit(1);
 17   }
 18
 19   fd = open(argv[1],O_CREAT|O_RDWR|O_TRUNC,0644);
 20   if(fd < 0){
 21     fprintf(stderr,"%s を開けませんでした\n",argv[1]);
 22     exit(1);
 23   }
 24   size = read(0, buf, BUFFER_SIZE);
 25   while(size > 1) {
 26     write(fd,buf,size);
 27     size = read(0, buf, BUFFER_SIZE);
 28   }
 29   close(fd);
 30   return 0;
 31 }

 このプログラムをビルド・実行すると以下のようになります。

$ gcc main.c
$ ./a.out
ファイル名を指定してください
$ ./a.out abc.txt
aaa
bbb
ccc

$ cat abc.txt
aaa
bbb
ccc
$ ls -l
合計 20
-rwxr-xr-x 1 komatsu komatsu 8632 10月 18 10:22 a.out
-rw-r--r-- 1 komatsu komatsu   12 10月 18 10:22 abc.txt
-rw-r--r-- 1 komatsu komatsu  683 10月 18 10:22 main.c

 このプログラムや入力した文字列をファイルに書き込みます。

 それとエンターキーのみを押すとループは途切れて終了するようになってます。

 ではファイル記述子を開くところから見て見ましょう。

 19   fd = open(argv[1],O_CREAT|O_RDWR|O_TRUNC,0644);
 20   if(fd < 0){
 21     fprintf(stderr,"%s を開けませんでした\n",argv[1]);
 22     exit(1);
 23   }

 まず O_CREAT を指定しているのでファイルが存在しない場合はファイルを新規作成し、O_RDWRを指定したことでファイルは読み書き両用となっています。

 O_TRUNC はファイルを上書きする際にファイルサイズを 0 にしてくれます。

 0644 はUNIX権限に翻訳すると「 -rw-r--r-- 」となります。

 6 は読み書きで 4 は読み込み専用に該当します。

 次は標準入力(キーボード)からの読み込みとファイルへの書き出し部分です。

 24   size = read(0, buf, BUFFER_SIZE);
 25   while(size > 1) {
 26     write(fd,buf,size);
 27     size = read(0, buf, BUFFER_SIZE);
 28   }
 29   close(fd);

 まず read で読み取るサイズは固定サイズ BUFFER_SIZE を指定します。

 buf には読み取れた分だけコピーされます。

 そして write では読み込んだバイトサイズを保持する size 変数を指定して fd に書き込みます。

 while ループ内の条件文で size を 1 より上としているのは、エンターキーを打ち込んだ際にループを終了するためです。

Copyright 2018-2019, by Masaki Komatsu