2016-09-05 42 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()可用。