使用C逐字节读取文件

时间:2018-07-07 15:47:08

标签: c hex byte

我试图逐字节读取文件,然后使用C将其打印出来,但是输出与十六进制编辑器的显示不匹配。

在十六进制编辑器中,前两行如下所示:

0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0111 1111 1000 0000 0000

预期输出:

00000000000000000000000000000000
00000000000001111111100000000000

但是当我的代码输出以下内容时:

00000000000000000000001111111100
00000000000000000000000000000000

这是我的代码:

#include <stdio.h>
#include <string.h>

int main() {
    FILE *fp;
    unsigned char buffer[4900] = "";
    int y;

    y = 0;
    fp = fopen("tugasz.ksa", "rb");

    for (int x = 0; x < 4900; x++) {
        fread(buffer, 1, 4900, fp);
        printf("%x", buffer[x]);
    }
    return (0);
}

2 个答案:

答案 0 :(得分:2)

您的代码中存在多个问题:

  • 您不会测试fopen是否失败,如果文件不存在或无法打开,则会导致不确定的行为。
  • 您不是在逐字节读取文件 ,而是在读取4900字节的块,而仅打印每个块一个字节。
  • 您可能很快就会到达文件末尾,但是您没有测试文件末尾,因此输出可能来自文件的同一部分。一个错误隐藏另一个错误的经典案例。
  • 转换格式%x每字节输出1或2个字符,具体取决于字节值。这是一个问题,因为文件内容分别是0x000x01,{{}的0x100x1101 1}}和10,因此显然是未对齐的输入。
  • 为了保持清洁,您应11溪流。
  • 根据发布的数据,不清楚十六进制编辑器是否以十六进制或二进制格式显示数据,以及值是基于字还是基于字节。

这是一种更简单的方法:

fclose

答案 1 :(得分:0)

for(int x = 0; x<4900; x++) {
   fread(buffer, 1, 4900, fp);
   printf("%x", buffer[x]);
}

在循环的第一次迭代中,这只会在buffer中以索引0打印第一个字符。

在第二次迭代中,这将在索引{1的buffer中打印第二个字符。

因此,如果您的文件少于4900字节,则仅打印1个字符。您获得更多输出的原因是因为到达文件末尾时循环不会中断。它主要打印垃圾,而不是实际的文件内容。

鉴于输入文件的十六进制视图,并且期望输出全为0和1,因此源文件不太可能是由0和1组成的字节的集合。相反,它可能包含字节从0到256,每个字节都是0和1位的集合。打印如下:

int main(void)
{
    FILE *fp = fopen("tugasz.ksa", "rb");
    if(fp)
    {
        unsigned char buffer[4096];
        size_t sz;
        int line = 0;
        while ((sz = fread(buffer, 1, sizeof(buffer), fp)) > 0)
        {
            for(int i = 0; i < sz; i++)
            {
                //print the bits of the byte, at buffer[i]:
                for(int j = 0; j < 8; j++)
                {
                    int mask = 1 << (7 - j);
                    int bit = buffer[i] & mask;
                    printf("%d", bit ? 1 : 0);
                }

                //add new line for every 4 byte
                line++;
                if((line % 4) == 0)
                    printf("\n");
            }
        }
    }

    return 0;
}

如果字节是0和1,则只需将其打印为printf("%d", buffer[i])printf("%02X", buffer[i])以获得字节值:

int main(void)
{
    FILE *fp = fopen("tugasz.ksa", "rb");
    if(fp)
    {
        unsigned char buffer[4096];
        size_t sz;
        while((sz = fread(buffer, 1, sizeof(buffer), fp)) > 0)
        {
            for(int i = 0; i < sz; i++)
                printf("%d", buffer[i]);
                //or use "%02X" instead, for printing the byte values:
                //printf("%02X ", buffer[i]);
        }
    }
    return 0;
}