【问题标题】:Hex file reading in C programming?在 C 编程中读取十六进制文件?
【发布时间】:2014-03-30 06:03:42
【问题描述】:

我有一个问题:

我正在编写一个功能类似于十六进制编辑器的 c 程序。我想获取一个文件并查看它的十六进制值。例如,假设我有一个文本文件“helloworld.txt”,其中仅包含“Hello World!”字样。在其中,我想指定程序获取该文件,读取其十六进制值(同样,该文件是一个简单的 .txt 文件,而不是二进制文件)并将其存储在一个数组中以备后用。

这是我目前所拥有的:

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

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

   printf("Enter the name of file you wish to see\n");
   gets(file_name);

   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);

   while( ( ch = fgetc(fp) ) != EOF )
      printf("%c",ch);

   fclose(fp);
   return 0;
}

如您所见,这实际上只是一个简单的文件,读取和打印内容。但是,问题是即使我处于“读取二进制”模式,它也不会给我文本文件的十六进制值。

我如何构造这个程序,以便它读取标准文本文件的十六进制值,然后 (a) 将它们放入一个数组中(我认为使用 for 循环应该足够简单)或 (b) 打印它们出现在屏幕上?

我尝试用谷歌搜索看看其他人是否也在尝试做同样的事情,但人们要么已经从二进制文件中读取,要么文件中已经有了十六进制值。我在常规 .txt 文件中有纯文本,但我想要下面的十六进制值(换句话说,文件的一种 hexdump)。我希望我的问题和我正在尝试做的事情是有意义的。如果您有任何问题,请随时告诉我!提前感谢您的所有帮助!我真的很感激!

【问题讨论】:

  • 永远不要使用gets()。
  • 而且...这只是一个表示问题,你printf("%c", ch);,所以你得到了char格式;喜欢printf("%02X", ch);,你会得到十六进制值。

标签: c file io hex hexdump


【解决方案1】:

你们离得太近了。
注意两件事:

1- 使用 fgets() 而不是 gets()。
2- printf("%02X",ch);

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

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;
}

当然,这只是打印到标准输出。如果你想把结果放入 一个数组,你可以像sprintf() 这样将你的输出放入一些缓冲区。

示例输出:

jrn@mint17 ~ $ ./a.out 
Enter the name of file you wish to see
hex_for_so.c
The contents of hex_for_so.c file are :
23 69 6E 63 6C 75 64 65 20 3C 73 74 64 69 6F 2E 
68 3E 0A 23 69 6E 63 6C 75 64 65 20 3C 73 74 64 
6C 69 62 2E 68 3E 0A 23 69 6E 63 6C 75 64 65 20 
3C 73 74 72 69 6E 67 2E 68 3E 0A 0A 69 6E 74 20 
6D 61 69 6E 28 29 0A 7B 0A 20 20 20 63 68 61 72 
20 63 68 2C 20 66 69 6C 65 5F 6E 61 6D 65 5B 32 
35 5D 3B 0A 20 20 20 46 49 4C 45 20 2A 66 70 3B 
0A 0A 20 20 20 70 72 69 6E 74 66 28 22 45 6E 74 
65 72 20 74 68 65 20 6E 61 6D 65 20 6F 66 20 66 
69 6C 65 20 79 6F 75 20 77 69 73 68 20 74 6F 20 
73 65 65 5C 6E 22 29 3B 0A 20 20 20 66 67 65 74 
73 28 66 69 6C 65 5F 6E 61 6D 65 2C 20 73 69 7A 
65 6F 66 28 66 69 6C 65 5F 6E 61 6D 65 29 2C 20 
73 74 64 69 6E 29 3B 0A 20 20 20 66 69 6C 65 5F 
6E 61 6D 65 5B 73 74 72 6C 65 6E 28 66 69 6C 65 
5F 6E 61 6D 65 29 2D 31 5D 20 3D 20 30 78 30 30 
3B 0A 0A 20 20 20 66 70 20 3D 20 66 6F 70 65 6E 
28 66 69 6C 65 5F 6E 61 6D 65 2C 22 72 62 22 29 
3B 20 2F 2F 20 72 65 61 64 20 62 69 6E 61 72 79 
20 6D 6F 64 65 0A 0A 20 20 20 69 66 28 20 66 70 
20 3D 3D 20 4E 55 4C 4C 20 29 20 2F 2F 65 72 72 
6F 72 20 63 68 65 63 6B 69 6E 67 0A 20 20 20 7B 
0A 20 20 20 20 20 20 70 65 72 72 6F 72 28 22 45 
72 72 6F 72 20 77 68 69 6C 65 20 6F 70 65 6E 69 
6E 67 20 74 68 65 20 66 69 6C 65 2E 5C 6E 22 29 
3B 0A 20 20 20 20 20 20 65 78 69 74 28 45 58 49 
54 5F 46 41 49 4C 55 52 45 29 3B 0A 20 20 20 7D 
0A 0A 20 20 20 70 72 69 6E 74 66 28 22 54 68 65 
20 63 6F 6E 74 65 6E 74 73 20 6F 66 20 25 73 20 
66 69 6C 65 20 61 72 65 20 3A 5C 6E 22 2C 20 66 
69 6C 65 5F 6E 61 6D 65 29 3B 0A 0A 20 20 20 69 
6E 74 20 69 3B 0A 20 20 20 77 68 69 6C 65 28 20 
28 20 63 68 20 3D 20 66 67 65 74 63 28 66 70 29 
20 29 20 21 3D 20 45 4F 46 20 29 0A 20 20 20 7B 
0A 20 20 20 20 20 20 70 72 69 6E 74 66 28 22 25 
30 32 58 20 22 2C 63 68 29 3B 0A 09 20 20 69 66 
28 20 21 28 2B 2B 69 20 25 20 31 36 29 20 29 20 
70 75 74 63 28 27 5C 6E 27 2C 20 73 74 64 6F 75 
74 29 3B 0A 20 20 20 7D 0A 20 20 20 66 63 6C 6F 
73 65 28 66 70 29 3B 0A 20 20 20 72 65 74 75 72 
6E 20 30 3B 0A 7D 0A 

【讨论】:

    【解决方案2】:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main(int argc, char **argv)
    {
        FILE *fd;
        long filesize;
        char *buffer, *it;
    
        if ((fd = fopen(argv[1], "rb")) == NULL) {
            perror("Error opening file");
            return EXIT_FAILURE;
        }
    
        fseek(fd, 0, SEEK_END);
        filesize = ftell(fd);
        rewind(fd);
    
        buffer = (char *) malloc(sizeof(char) * filesize+1);
    
        if (fread(buffer, sizeof(char), filesize, fd) != filesize) {
            fprintf(stderr, "Error reading file\n");
            return EXIT_FAILURE;
        }
    
        buffer[filesize] = '\0';
    
        for (it = buffer; *it != '\0'; it++)
            printf("%02X ", *it);
    
        free(buffer);
    
        return EXIT_SUCCESS;
    }
    

    【讨论】:

    • 感谢您的回复和帮助!你能为我解释一下这部分代码吗? : fseek(fd, 0, SEEK_END);文件大小 = ftell(fd);倒带(fd);如果我想将这些结果输出到数组,我可以做些什么不同的事情?
    • 当然:fseek()-ftell()-rewind() 块是获取您将要阅读的文件大小的相当标准的方法;这样,您可以动态分配内存缓冲区的大小,使其与文件大小完全相同,不多也不少。对于数组问题,您必须注意buffer 已经是您的数组!这只是表示的问题:在缓冲区的每个元素中都有一个字符,即 8 位组成该字符的 ASCII 表示。但是,与此同时,您可以将这 8 位视为 2 个十六进制符号(每个 4 位)继续
    • (...) 这正是 for 循环内的 printf() 所做的,只是打印数组值,每次一个元素,作为十六进制数字而不是字符。我们可以将它们打印为整数(以 10 为基数)数字,这样您就会得到类似 72 101 108 108 111 的“Hello”。您真正需要了解的唯一一件事是,从您从磁盘读取文件的那一刻起,您的字符、十进制数字、十六进制数字(您的名字)就已经在 buffer 数组中了;从那时起,如何解释这些数据取决于您。
    【解决方案3】:

    不知道我是否正确理解了这个问题,但不是这样(对于选项 B)简单地使用

    printf("0X%02x ", ch);
    

    【讨论】:

    • 非常感谢您的回复和帮助!上面 cmets 中你的 printf 语句和 moeCake 的 printf 语句有什么区别?我可以使用相同的方法将这些十六进制值输出到数组吗?
    • 真的没有区别 - 我所做的只是在十六进制字节前面打印“0X”,然后在它后面打印一个空格,所以你会得到类似“0XAA 0X2E”的东西,在 moeCake 的建议中你会得到“ AA2E"。
    • 至于将值放入数组中,取决于您要执行的操作 - 如果您要写入字符的实际二进制字节值,请使用下面的 asamarin 方法。如果您想编写字节的文本表示(即“0XAA”),那么您可能想要使用 fprintf - 请记住,数组的大小将是源文件中的字节数乘以 5。
    猜你喜欢
    • 2012-04-04
    • 2015-05-01
    • 2011-10-07
    • 2015-01-26
    • 2016-08-10
    • 2015-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多