【问题标题】:Hex file reading in C, some data corrupted?用 C 读取十六进制文件,某些数据已损坏?
【发布时间】:2016-03-24 15:40:37
【问题描述】:

我的学校项目有问题。当我尝试从 C 程序中读取二进制文件中的一些十六进制数据时,我得到一些填充有 F 的数据,就像这样

00 64 61 56 03 00 00 00 09 00 00 00 73 00 00 00 
6A 69 75 FFFFFFE8 FFFFFFD1 5B FFFFFF8C FFFFFF93 73 FFFFFFAF 19 FFFFFF87 FFFFFFC1 4D FFFFFFFD FFFFFF93 
FFFFFFDF FFFFFFBE FFFFFFA0 09 FFFFFFBE FFFFFFD4 FFFFFFEB FFFFFFDE FFFFFFD3 FFFFFFF9 FFFFFFBD FFFFFFE6 FFFFFFFA FFFFFFAA 7E 29 
FFFFFFD3 FFFFFFE2 13 FFFFFFA5 3F FFFFFFA0 3A FFFFFFB2 50 53 3B 12 FFFFFFA1 39 FFFFFFA6 FFFFFF82 
FFFFFFF7 

虽然 hexdump 中的原始文件如下所示:

0000000 6400 5661 0003 0000 0009 0000 0073 0000
0000010 696a e875 5bd1 938c af73 8719 4dc1 93fd
0000020 bedf 09a0 d4be deeb f9d3 e6bd aafa 297e
0000030 e2d3 a513 a03f b23a 5350 123b 39a1 82a6
0000040 00f7

我不确定,为什么会这样。

我使用this 代码对其进行了测试:

int main()
{
   char ch, file_name[25];
   FILE *fp;

   printf("Enter the name of file you wish to see\n");
   fgets(file_name, sizeof(file_name), stdin);
   file_name[strlen(file_name)-1] = 0x00;

   fp = fopen(file_name,"rb"); // read binary mode

   if( fp == NULL ) //error checking
   {
      perror("Error while opening the file.\n");
      exit(EXIT_FAILURE);
   }

   printf("The contents of %s file are :\n", file_name);

   int i;
   while( ( ch = fgetc(fp) ) != EOF )
   {
      printf("%02X ",ch);
      if( !(++i % 16) ) putc('\n', stdout);
   }
   fclose(fp);
   putc('\n', stdout);

   return 0;
}

【问题讨论】:

  • 没有“十六进制数据”。十六进制只是表示数据的一种方式。您可以在任何其他数字系统中表示完全相同的数据。

标签: c


【解决方案1】:

将文件作为二进制文件打开并尝试通过处理文本文件的fgetc() 读取它可能不是一个好主意。相反,您可以使用fread() 来读取二进制文件。

这是我的解决方案:

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

int main()
{
    char file_name[25];
    puts("Enter the name of file you wish to see");
    fgets(file_name, sizeof (file_name), stdin);
    file_name[strlen(file_name) - 1] = '\0';

    FILE *fp;
    fp = fopen(file_name, "rb"); // read binary mode

    if(!fp) //error checking
    {
        perror("fopen()");
        exit(EXIT_FAILURE);
    }

    fseek (fp, 0, SEEK_END); // non-portable
    long fSize = ftell(fp);
    rewind(fp);

    printf("The contents of %s file are :\n", file_name);

    uint8_t *ch = malloc(fSize); // assuming CHAR_BIT == 8
    fread(ch, 1, fSize, fp);

    int i;
    for(i = 0; i < fSize; i++)
    {
        printf("%.2x ", ch[i]);
        if(!((i + 1) % 16))
            putchar('\n');
    }
    fclose(fp);
    putchar('\n');

    return EXIT_SUCCESS;
}

这段代码已经在我的机器上测试过了,它的输出和hex dump的输出是一样的。请随时向我询问详细信息。

【讨论】:

    【解决方案2】:

    在将有符号整数值扩展为更大的整数类型时,您刚刚被处理器完成的符号扩展绊倒了:

    char 类型只有一个字节宽,而printf() 函数需要int 参数(在您的系统上为四个字节)。由于char 已在您的系统上签名,其他 24 位将填充符号位的副本,从而生成您在输出中看到的FFFFFF 模式。请注意,您的输出是正确的,除了以大于或等于 8 的十六进制数字开头的所有字节的 FFFFFF 前缀。

    您可以通过简单地将ch 声明为unsigned char 来避免这种情况。这将零扩展到int,并且您的输出将是正确的。

    【讨论】:

      【解决方案3】:

      如果您将 ch 设为无符号字符,您将看不到符号扩展名(FF)。

      【讨论】:

        【解决方案4】:

        将 ch 设为无符号字符,因为它将二进制值视为有符号,将 MSB 视为符号位。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-04-04
          • 1970-01-01
          • 1970-01-01
          • 2015-05-01
          • 1970-01-01
          • 1970-01-01
          • 2015-07-30
          • 2020-10-25
          相关资源
          最近更新 更多