2016-09-05 10 views
1

私はCの新人ですbase64の自分のバージョンを作りようとしています。プログラムはstdinから入力を受け取り、stdoutに相当するbase64を出力します。私のプログラムをバイナリファイルに対してテストしている間に、stdinのfread-ingが、実際にEOFに達する前に早期に短いカウントを返すように思えました。ここでfreadが早急にEOFをバイナリファイルで通知しています

は私の主な方法の関連部分である:

int main(void) 
{ 
    unsigned char buffer[BUFFER_SIZE]; 
    unsigned char base64_buffer[BASE64_BUFFER]; 

    while (1) 
    { 
     TRACE_PUTS("Reading in data from stdin..."); 
     size_t read = fread(buffer, 1, sizeof(buffer), stdin); /* Read the data in using fread(3) */ 

     /* Process the buffer */ 

     TRACE_PRINTF("Amount read: %zu\n", read); 
     TRACE_PUTS("Beginning base64 encode of buffer"); 
     size_t encoded = base64_encode(buffer, read, base64_buffer, sizeof(base64_buffer)); 

     /* Write the data to stdout */ 
     TRACE_PUTS("Writing data to standard output"); 
     ... 

     if (read < sizeof(buffer)) 
     { 
      break; /* We reached EOF or had an error during the read */ 
     } 
    } 

    if (ferror(stdin)) 
    { 
     /* Handle errors */ 
     fprintf(stderr, "%s\n", "There was a problem reading from the file."); 
     exit(1); 
    } 

    puts(""); /* Output a newline before finishing */ 

    return 0; 
} 

あなたが見ることができるように、メインループがバッファに標準入力にfreadすべての反復を呼び出し、その後、最後のチェックで読み取ら量が少ない場合バッファのサイズより大きい。そうであれば、エラー(0の場合)またはEOFに達したと判断し、ループを終了します。数を返す)成功した​​

、関数fread()とfwriteの(:

は、私は関数freadのmanページから、この引用に基づいて、というだけで!= 0より、< sizeof(buffer)するreadを確認してOKであると仮定しています読み書きされたアイテムの数。この数値は、サイズが1の場合にのみ転送されるバイト数になります。エラーが発生した場合、またはファイルの末尾に達した場合、戻り値は短い項目数(またはゼロ)です。

これは、フルバッファが読み込まれないと、EOFに達したことを意味します。その確立して

が、これは私がcat /bin/echoに対する私のアプリを実行したときに私が手にトレースです:

$ cat /bin/echo | bin/base64 >/dev/null # only view the trace output 
TRACE: C:/Users/James/Code/c/base64/main.c:23: Reading in data from stdin... 
TRACE: C:/Users/James/Code/c/base64/main.c:28: Amount read: 600 
TRACE: C:/Users/James/Code/c/base64/main.c:29: Beginning base64 encode of buffer 
TRACE: C:/Users/James/Code/c/base64/main.c:43: Writing data to standard output 
TRACE: C:/Users/James/Code/c/base64/main.c:23: Reading in data from stdin... 
TRACE: C:/Users/James/Code/c/base64/main.c:28: Amount read: 600 
TRACE: C:/Users/James/Code/c/base64/main.c:29: Beginning base64 encode of buffer 
TRACE: C:/Users/James/Code/c/base64/main.c:43: Writing data to standard output 
TRACE: C:/Users/James/Code/c/base64/main.c:23: Reading in data from stdin... 
TRACE: C:/Users/James/Code/c/base64/main.c:28: Amount read: 600 
TRACE: C:/Users/James/Code/c/base64/main.c:29: Beginning base64 encode of buffer 
TRACE: C:/Users/James/Code/c/base64/main.c:43: Writing data to standard output 
TRACE: C:/Users/James/Code/c/base64/main.c:23: Reading in data from stdin... 
TRACE: C:/Users/James/Code/c/base64/main.c:28: Amount read: 569 
TRACE: C:/Users/James/Code/c/base64/main.c:29: Beginning base64 encode of buffer 
TRACE: C:/Users/James/Code/c/base64/main.c:43: Writing data to standard output 

$ 

をそしてここで実際にどのように/bin/echo大きい:あなたが見ることができるように

$ cat /bin/echo | wc -c 
28352 

、ファイル全体の長さは28352バイトですが、アプリケーションは停止する前に約2400バイトしか読み込みません。どんな考え? freadはヌルターミネータを特別に処理しますか?

GCCでMinGW-w64を使用しています。ありがとう。

答えて

3

Windowsを使用していますか?はい、パス名はC:で始まります。ファイルにControl-Z('\x1A'または'\32')文字が含まれている可能性があります。それは何らかの形でそれを調整しない限り、標準入力をバイナリファイルとして扱わないので、Control-Zは入力の終わりを示します(Windows Cランタイム、したがってあなたのプログラム)。

モードを調整するために「何とか」可能な1つは_set_fmode()です。しかし、あなたが_setmode()を必要とする可能性が高いです。

_setmode(fileno(stdin), O_BINARY); 

私はそうするための最善または唯一の方法だかどうかの判断を留保します。マニュアルだけでなく、私ができることを研究することができます。 Microsoftの世界でfileno()(おそらく_fileno())が使用可能であることをテストする方法はありません。

関連する問題