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