前回はシステムコールを使ってファイル読み出しをしたので、
今回はライブラリ関数を使ってファイル読み出ししてみます。
man 3でそれぞれ型の確認。
FOPEN(3) Linux Programmer's Manual FOPEN(3) 名前 fopen, fdopen, freopen - ストリームを開く関数 書式 #include <stdio.h> FILE *fopen(const char *path, const char *mode); FILE *fdopen(int fd, const char *mode); FILE *freopen(const char *path, const char *mode, FILE *stream);
FGETC(3) Linux Programmer's Manual FGETC(3) 名前 fgetc, fgets, getc, getchar, ungetc - 文字と文字列の入力 書式 #include <stdio.h> int fgetc(FILE *stream); char *fgets(char *s, int size, FILE *stream); int getc(FILE *stream); int getchar(void); int ungetc(int c, FILE *stream);
PUTS(3) Linux Programmer's Manual PUTS(3) 名前 fputc, fputs, putc, putchar, puts - 文字と文字列の出力 書式 #include <stdio.h> int fputc(int c, FILE *stream); int fputs(const char *s, FILE *stream); int putc(int c, FILE *stream); int putchar(int c); int puts(const char *s);
FCLOSE(3) Linux Programmer's Manual FCLOSE(3) 名前 fclose - ストリームを閉じる 書式 #include <stdio.h> int fclose(FILE *stream);
ではプログラムです。バッファがいらない分、すっきりしています。
takk@deb9:~/tmp$ cat -n fgetcfputc.c 1 #include <stdio.h> 2 3 int main() 4 { 5 int c; 6 FILE *fp; 7 fp = fopen("test.dat","r"); 8 while((c=fgetc(fp)) != -1){ 9 fputc(c,stdout); 10 } 11 fclose(fp); 12 13 return 0; 14 } takk@deb9:~/tmp$
実行してみます。
takk@deb9:~/tmp$ gcc -o b.out fgetcfputc.c takk@deb9:~/tmp$ ./b.out 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 takk@deb9:~/tmp$
問題なさそうです。
前回作ったシステムコールを使ったファイル読み出しの実行ファイル(a.out)と比較してみます。サイズ比較。
takk@deb9:~/tmp$ wc -c a.out b.out 8784 a.out 8832 b.out 17616 合計 takk@deb9:~/tmp$
ちょっとだけb.outの方が大きいです。ライブラリを使用するのでその分大きくなるのでしょうか。
処理時間もそれぞれ確認。余計な表示がでないように/dev/nullに読み出した値を捨てます。
takk@deb9:~/tmp$ time ./a.out >/dev/null real 0m0.004s user 0m0.000s sys 0m0.000s takk@deb9:~/tmp$ time ./b.out >/dev/null real 0m0.004s user 0m0.000s sys 0m0.000s takk@deb9:~/tmp$
test.datのファイルサイズが小さいから、ほとんど差が分かりません。
test.datを一旦削除して、1Gのtest.datを生成します。
takk@deb9:~/tmp$ rm test.dat takk@deb9:~/tmp$ truncate -s1G test.dat takk@deb9:~/tmp$ ls -lh test.dat -rw-r--r-- 1 takk takk 1.0G 4月 11 20:40 test.dat takk@deb9:~/tmp$
さて比較します。
まずはシステムコール版。
takk@deb9:~/tmp$ time ./a.out >/dev/null real 0m8.130s user 0m0.356s sys 0m2.292s takk@deb9:~/tmp$
1Gともなると結構かかるものですね。8秒かかりました。
次はライブラリ版。
takk@deb9:~/tmp$ time ./b.out >/dev/null real 0m36.147s user 0m11.792s sys 0m0.188s takk@deb9:~/tmp$
システムコールと比べて、4倍以上時間がかかりました。
連続したデータなら直接システムコールを使った方が早いということでしょうか。
コメント