続きです。
今回は、ファイルの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$
コメント