lseek() 関数はファイルオフセットを調整してくれる関数です。
ファイルオフセットとは読み込む開始位置です。
#include <sys/types.h> #include <unistd.h> off_t lseek(int fd, off_t offset, int whence);
fd はファイル記述子で off_t はオフセット、 whence は以下の3種類のいずれかとなります。
whence にはそれ以外の種類もあるようですが、この項目ではこの3つだけ使ってみたいと思います。
それで実装例を見てみましょう。
main.c.
1 #include <sys/types.h> 2 #include <unistd.h> 3 #include <fcntl.h> 4 #include <stdio.h> 5 #include <stdlib.h> 6 7 int main() 8 { 9 char *buf; 10 int fd, size, pos; 11 12 buf = (char *) calloc(100, sizeof(char)); 13 fd = open("abc.txt", O_RDONLY); 14 if (fd < 0) { 15 perror("r1"); 16 exit(1); 17 } 18 19 size = read(fd, buf, 5); 20 printf("read(%d, buf, 5)\n", fd); 21 printf("%d バイト\n", size); 22 buf[size] = '\0'; 23 printf("%s\n\n", buf); 24 25 pos = lseek(fd, 2, SEEK_CUR); 26 printf("lseek(%d, 2, SEEK_CUR) => %d\n", fd,pos); 27 size = read(fd, buf, 5); 28 printf("read(%d, buf, 5) => %d\n",fd,size); 29 printf("%s\n\n",buf); 30 31 pos = lseek(fd, 0, SEEK_SET); 32 printf("lseek(%d,0,SEEK_SET) => %d\n",fd,pos); 33 size = read(fd, buf, 5); 34 printf("read(%d, buf, 5) => %d\n",fd,size); 35 buf[size] = '\0'; 36 printf("%s\n\n", buf); 37 38 pos = lseek(fd,-10,SEEK_END); 39 printf("lseek(%d, -10, SEEK_END) => %d\n",fd,pos); 40 size = read(fd, buf, 5); 41 printf("read(%d, buf, 5) => %d\n", fd,size); 42 buf[size] = '\0'; 43 printf("%s\n", buf); 44 45 return 0; 46 }
ビルドと実行結果.
$ echo "abcde123456789" > abc.txt $ gcc main.c $ ./a.out read(3, buf, 5) 5 バイト abcde lseek(3, 2, SEEK_CUR) => 7 read(3, buf, 5) => 5 34567 lseek(3,0,SEEK_SET) => 0 read(3, buf, 5) => 5 abcde lseek(3, -10, SEEK_END) => 5 read(3, buf, 5) => 5 12345
出力が長めですね…
すんません… (´・ω・`)
それで最初の出力部分です。
19 size = read(fd, buf, 5); 20 printf("read(%d, buf, 5)\n", fd); 21 printf("%d バイト\n", size); 22 buf[size] = '\0'; 23 printf("%s\n\n", buf);
まあこれは「read(fd,buf,5)」によって 5 バイトだけ buf に読みこんでるだけですね。
まだこの段階で lseek() 関数は使ってません。
では次の出力を見たいと思いますが、空の行があいたコードのことです。
25 pos = lseek(fd, 2, SEEK_CUR); 26 printf("lseek(%d, 2, SEEK_CUR) => %d\n", fd,pos); 27 size = read(fd, buf, 5); 28 printf("read(%d, buf, 5) => %d\n",fd,size); 29 printf("%s\n\n",buf);
「 lseek(3, 2, SEEK_CUR) 」というのは SEEK_CUR が 5 になってるので、それにオフセット 2 を足すと 7 バイトになりますね。
なので lseek() は 7 を返します。
そして「 read(3, buf, 5) 」は 5 を返します。
buf の中身は 7 バイトオフセットを移動してから read() で 5 バイトを読み込んでるので「34567」を出力します。
では次の出力に該当するコードです。
31 pos = lseek(fd, 0, SEEK_SET); 32 printf("lseek(%d,0,SEEK_SET) => %d\n",fd,pos); 33 size = read(fd, buf, 5); 34 printf("read(%d, buf, 5) => %d\n",fd,size); 35 buf[size] = '\0'; 36 printf("%s\n\n", buf);
「 lseek(3,0,SEEK_SET) 」はファイルオフセットを 0 の位置に戻します。
なぜなら SEEK_SET は offset 引数に指定した値をファイルオフセットに指定するからです。
この場合は offset 引数は 0 なのでファイルオフセットは 0 になります。
では最後の出力箇所に該当するコードです。
38 pos = lseek(fd,-10,SEEK_END); 39 printf("lseek(%d, -10, SEEK_END) => %d\n",fd,pos); 40 size = read(fd, buf, 5); 41 printf("read(%d, buf, 5) => %d\n", fd,size); 42 buf[size] = '\0'; 43 printf("%s\n", buf);
「 lseek(3, -10, SEEK_END) 」はファイルサイズ、すなわちファイルの終わりのファイルオフセットから -10 の位置を返します。
つまり lseek() は 5 を返します。
それと「read(3, buf, 5)」は 5 バイトだけ buf を読み込みます
位置が 5 で 5 バイト読み込みます。
buf を printf() で出力すると「 12345 」になります。
Copyright 2018-2019, by Masaki Komatsu