为什么fread()没有得到预期的字节?

时间:2016-03-15 14:47:34

标签: c file null fread

我尝试使用C在二进制模式下读取文件,但它只在缓冲区中存储前43个字符。 我想以245字节为一组读取文件。它包含多字符字节和空字符。 这是十六进制文件的内容:

323031353037303735393036333130343739332032373231333732534e30323033323545533036303130340000000008557c0000000000693c0000000000000c0000000008557c0000000000693c0000000000000c0000000008557c0000000000693c0000000000000c00001c00001c00001c00000c00000c00000c00001c4d4e202020204942202020204f393920202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202039444b524d4144

这是我的代码:

char* to_hex(const char* strin) {
    char * strout = malloc(2 * strlen(strin) + 1);
    int x;

    for (x = 0; x < strlen(strin);x++){
        sprintf(&strout[x+x],"%02x", (int)(*(unsigned char*)(&strin[x])) );
    }

    strout[2 * strlen(strin)]='\0'
    return strout;
}

int main(int argc, char *argv[]) {

    FILE * pfinput = fopen("stack.bin", "rb");
    int lrec = 245;
    char* sbuff = (char *)malloc((lrec + 1) * sizeof(char));

    if (pfinput != NULL) {
        while (fread (sbuff, 1, lrec, pfinput) > 0){
            sbuff[lrec] = '\0';

            printf("len=%d hex=%s\n\n", strlen(sbuff), to_hex(sbuff) );

        }
    }

    return 0;
}

返回以下内容:

len=43 hex=323031353037303735393036333130343739332032373231333732534e3032303332354553303630313034
  

为什么它只能读取43个字符而不是245个字符?   你还有其他选择吗?

2 个答案:

答案 0 :(得分:1)

当您的字符串嵌入空字符时,您无法使用strlen可靠地计算字符数。您需要捕获fread读取的字符数并使用它。

int nread = 0;
while (( nread = fread (sbuff, 1, lrec, pfinput)) > 0)    

而不是

printf("len=%d hex=%s\n\n", strlen(sbuff), to_hex(sbuff) );

您需要使用:

printf("len=%d hex=%s\n\n", nread, to_hex(sbuff) );

您还需要将nread传递给to_hex,以便您能够在该功能中正确处理嵌入的空字符。

char* to_hex(const char* strin, int nread) {
    char * strout = malloc(2 * nread + 1);
    int x;

    for (x = 0; x < nread; x++){
        sprintf(&strout[x+x],"%02x", (int)(*(unsigned char*)(&strin[x])) );
    }

    strout[2 * nread]='\0';
    return strout;
}

之后,printf行必须是:

printf("len=%d hex=%s\n\n", nread, to_hex(sbuff, nread) );

PS 请注意,您在此处泄漏内存。由to_hex分配的内存用于printf的调用,但之后不会被释放。您可能希望在变量中捕获该内存并释放它。

char* hexstring = to_hex(sbuff, nread);
printf("len=%d hex=%s\n\n", nread, hexstring);
free(hexstring);

此外,在从sbuff返回之前解除分配main

free(sbuff);

PS 2 我会简化这一行

        sprintf(&strout[x+x],"%02x", (int)(*(unsigned char*)(&strin[x])) );

        int c = strin[x];
        sprintf(&strout[x+x],"%02x", c );

答案 1 :(得分:0)

&#39;成功完成后,fread()将返回成功读取的元素数量&#39;,

fread()返回的vaue是确定已经读入缓冲区的字节数的唯一方法。在文件的末尾,有可能小于&#39; lrec&#39;可以阅读字符。