続きです。
今回は、ファイルの10Byte末尾を出力するプログラムを作ります。
前回確認したfseekで末尾からのオフセットを-10にして読み込んで表示すれば良いだけですが、サイズが10Byte未満のファイルにも対応するので、チェック処理も充実していきます。
まずは、引数で指定したファイルを読み込んで、固定で末尾10Byteを表示するプログラム。
1 #include <stdio.h>
2
3 int main(int argc, char* argv[])
4 {
5 int c;
6 FILE *fp;
7 char *fname;
8
9 fname = argv[1];
10
11 fp=fopen(fname,"r");
12 if(fseek(fp,-10,SEEK_END) != 0){
13 perror("ERROR");
14 }
15 while((c=fgetc(fp)) != -1){
16 putchar(c);
17 }
18 fclose(fp);
19
20 return 0;
21 }
エラー処理はほとんど入ってません。そのうち入れます。
では、読み出すファイルa.txtを作成します。
takk@deb9:~/tmp$ seq -s, 10 | tee a.txt 1,2,3,4,5,6,7,8,9,10 takk@deb9:~/tmp$
ビルドして、実行します。引数に作成したa.txtを指定します。
takk@deb9:~/tmp$ gcc t.c takk@deb9:~/tmp$ ./a.out a.txt ,7,8,9,10 takk@deb9:~/tmp$
末尾10Byteのみ表示されました。
少し分かりにくいので、wcでカウントしてみます。
takk@deb9:~/tmp$ ./a.out a.txt | wc -c 10 takk@deb9:~/tmp$
10Byteですね。
改行を入れて10Byteです。
takk@deb9:~/tmp$ ./a.out a.txt | od -tx1c
0000000 2c 37 2c 38 2c 39 2c 31 30 0a
, 7 , 8 , 9 , 1 0 \n
0000012
takk@deb9:~/tmp$
次は、10Byte未満ファイル、b.txtを作成します。
takk@deb9:~/tmp$ echo -ne "\x1\x2\x3" > b.txt
3Byteのファイルです。
これを最初に作った末尾10Byte表示プログラムの引数に指定します。
takk@deb9:~/tmp$ ./a.out b.txt | od -tx1 ERROR: Invalid argument 0000000 01 02 03 0000003 takk@deb9:~/tmp$
ERRORが発生しました。fseekにファイルサイズを超えたオフセットを指定したため、失敗 となりました。
次は、エラーチェックを少しだけ入れます。
ファイル読み込み前に、stat関数で、ファイルサイズを取得し、
10 Byte未満なら、fseekで末尾からのオフセットをファイルサイズと同じ値にしています。
takk@deb9:~/tmp$ cat -n t.c
1 #include <stdio.h>
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <unistd.h>
5
6 int main(int argc, char* argv[])
7 {
8 int c;
9 FILE *fp;
10 char *fname;
11 struct stat fs;
12 int len = 10;
13
14 fname = argv[1];
15
16 stat(fname, &fs);
17
18 len = fs.st_size < 10 ? fs.st_size : 10;
19
20 fp=fopen(fname,"r");
21 if(fseek(fp,-len,SEEK_END) != 0){
22 perror("ERROR1");
23 }
24 while((c=fgetc(fp)) != -1){
25 putchar(c);
26 }
27 fclose(fp);
28
29 return 0;
30 }
takk@deb9:~/tmp$
ビルド後、実行すると、エラーは発生しなくなりました。
takk@deb9:~/tmp$ ./a.out b.txt | od -tx1 0000000 01 02 03 0000003 takk@deb9:~/tmp$


コメント