2016-09-05 43 views
1

我是C的新手。我試圖做我自己的版本base64;該程序從stdin獲取輸入並將其base64等效值輸出到stdout。在針對二進制文件測試我的程序時,我注意到來自stdin的fread -ing似乎在實際到達EOF之前早些時候返回一個短計數。fread過早地用二進制文件發信號EOFOFF

這裏是我的主要方法的相關部分:

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已達到,並退出循環。

我假定它是確定檢查read< sizeof(buffer),而不僅僅是!= 0的基礎上,從FREAD的手冊頁這句話:

成功時,FREAD()和fwrite()返回數的項目讀取或寫入。此數字等於僅在大小爲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專門處理空終止符嗎?

如果有幫助,我正在使用MinGW-w64和GCC;謝謝。

回答

3

你在Windows上嗎?是的,路徑名開頭C:就是這樣。您可能在文件中有Control-Z('\x1A''\32')字符。它(Windows C運行時,因此也就是你的程序)不會將標準輸入視爲二進制文件,除非你以某種方式調整它,所以Control-Z標記輸入結束。

一個可能的'莫名其妙'來調整模式是_set_fmode()。然而,更有可能的是,你需要_setmode()

_setmode(fileno(stdin), O_BINARY); 

我保留對不管是這樣做的最佳或唯一方法判斷。你可以儘可能的研究手冊。我無法測試fileno()或者微軟世界中的_fileno()可用。