自作のtail(その3)

続きです。

今回は、ファイルの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$ 

コメント

タイトルとURLをコピーしました