简体   繁体   English

C 语言的 hexdump 程序

[英]hexdump program in C language

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 255

void hexDump (char *desc, void *addr, int len) {
    int i;
    unsigned char buffLine[17];
    unsigned char *pc = (unsigned char*)addr;


    if (desc != NULL){

       printf ("%s:\n", desc);

    }


    for (i = 0; i < len; i++) {


        if ((i % 16) == 0) {

            if (i != 0)

                printf ("  %s\n", buffLine);
           // if (buffLine[i]== '\0') break;

            if (pc[i] == 0x00) exit(0);

            // Prints the ADDRESS
            printf ("  %07x ", i);
        }

        // Prints the HEXCODES that represent each chars.
        printf ("%02x", pc[i]);
        if ((i % 2) == 1) 
            printf (" "); 



        if ((pc[i] < 0x20) || (pc[i] > 0x7e)){
            buffLine[i % 16] = '.';
        }

        else{

           buffLine[i % 16] = pc[i];

        }    


        buffLine[(i % 16) + 1] = '\0'; //Clears the next array buffLine


    }



    while ((i % 16) != 0) {
        printf ("   ");
        i++;
    }


    printf ("  %s\n", buffLine);
}

//----------------------------------------------

int main()
    {
            FILE *ptr_file;
            char buff[SIZE];

            ptr_file =fopen("input.txt","r");
            if (!ptr_file){
            printf("returning 1");
                return 1;
            }

            memset(buff, '\0', sizeof( buff) );
            fgets(buff,SIZE, ptr_file);
            hexDump ("buff", &buff, sizeof (buff));

        fclose(ptr_file);

            return 0;
    }
    //*/

Sorry, this I'm new to C, so it's kinda of messy right now, I been deleting parts and making temporary codes, etc... So anyways this works by reading characters from input.txt and outputs it by printing the hexidecimal representation and the Acii representations on the right.抱歉,我是 C 的新手,所以现在有点乱,我一直在删除零件并制作临时代码等...所以无论如何,这可以通过从 input.txt 读取字符并通过打印十六进制表示来输出以及右侧的 Acii 表示。 For bytes forming non-printable characters, print a '.'对于形成不可打印字符的字节,打印一个 '.' character (a dot/period character, ie hex value 2E).:字符(点/句点字符,即十六进制值 2E)。:

0003540: 0504 0675 6e73 6967 6e65 6420 6368 6172 ...unsigned char
0003550: 0008 0107 0000 0131 0675 6e73 6967 6e65 .......1.unsigne

BUT my program does not print anything beyond the 'new line' in the text.但是我的程序不会打印文本中“新行”之外的任何内容。 For example: in my input.txt, I have:例如:在我的 input.txt 中,我有:

This is line 1 so this will be longer than usual
line 2 is this
this is the last line

after reading my program, it only outputs like this:阅读我的程序后,它只输出如下:

  0000000 5468 6973 2069 7320 6c69 6e65 2031 2073   This is line 1 s
  0000010 6f20 7468 6973 2077 696c 6c20 6265 206c   o this will be l
  0000020 6f6e 6765 7220 7468 616e 2075 7375 616c   onger than usual
  0000030 0a00 0000 0000 0000 0000 0000 0000 0000   ................

But for some reason it won't print and hex the second, third line....但由于某种原因,它不会打印和十六进制第二,第三行....

You call fgets only once. 您只调用一次fgets fgets reads a line from the file and stops when it exhausts the SIZE char limit, when it hits the end of the file or when it encounters a newline character. fgets从文件中读取一行,并在耗尽SIZE字符限制,到达文件末尾或遇到换行符时停止。 So that behaviour is to be expected. 这样的行为是可以预期的。

The length of the data will usually be less than the char limit, but you print all SIZE chars, which gives you the zeros. 数据的长度通常小于字符数限制,但是您将打印所有SIZE字符,这将为零。

If you want to treat all lines, you should cal fgets in a loop and break it when it returns NULL . 如果要处理所有行,则应在循环中校准fgets ,并在返回NULL时将其中断。 You should also pass strlen(buf) as length parameter instead of sizeof(buf) , which will give you the usually overlong SIZE . 您还应该传递strlen(buf)作为长度参数,而不是sizeof(buf) ,这通常会给您超长的SIZE

The purpose of a hex dumper is to make the data of any file visible. 十六进制转储程序的目的是使任何文件的数据可见。 You use fgets and char , which should be used for text files. 您使用fgetschar ,应将其用于文本文件。 (I'm not sure what fgets does when it encounters a null byte, for example.) (例如,我不确定fgets遇到空字节时会做什么。)

It is therefore better to use bytes, ie an unsigned char and read them block-wise with fread . 因此,最好使用字节(即unsigned char并使用fread逐块读取它们。 If you make the block-size a multiple of 16, this will help you to format your output. 如果将块大小设为16的倍数,这将帮助您格式化输出。 So: 所以:

for (;;) {
    unsigned char buf[SIZE];
    size_t n = fread(buf, 1, SIZE, f);

    if (n > 0) dump(buf, n);
    if (n < SIZE) break;
}

You need to open the file in binary mode using "rb" not "r" 您需要使用“ rb”而非“ r”以二进制模式打开文件

Then use fread() to read from the file, either by reading chunks from it or by reading the whole file. 然后使用fread()从文件中读取数据,方法是从文件中读取大块数据,或者读取整个文件。

You should use fread() to read the file, and put that in a loop (until it returns 0), so that it reads the whole file. 您应该使用fread()读取文件,并将其放入循环中(直到返回0),以便读取整个文件。 If you are on Windows also make sure to open the file with "rb" (binary mode), while on Unix it shouldn't matter. 如果您在Windows上,也请确保使用“ rb”(二进制模式)打开文件,而在Unix上则没有关系。

One last suggestion would be to use isascii() or one of its sister functions, instead of manually checking for "printability". 最后的建议是使用isascii()或其姊妹函数之一,而不是手动检查“可打印性”。 See http://linux.die.net/man/3/isalnum . 参见http://linux.die.net/man/3/isalnum

I'm doing the same problem but for both binary dump & hexdump.我正在做同样的问题,但对于二进制转储和十六进制转储。 However, for the last line of output, it isn't in the right place.但是,对于最后一行输出,它不在正确的位置。 Please help.请帮忙。 Thank you!谢谢!

The following is what I use if the last line does not have 16 characters.如果最后一行没有 16 个字符,以下是我使用的内容。 while((i%16) != 0) { printf(" "); i++; }<\/code>

"

void HexDump(const void* data, size_t size) 
{
    char ascii[17];
    size_t i, j;
    ascii[16] = '\0';
    for (i = 0; i < size; ++i) {
        printf("%02X ", ((unsigned char*)data)[i]);
        if (((unsigned char*)data)[i] >= ' ' && ((unsigned char*)data)[i] <= '~') {
            ascii[i % 16] = ((unsigned char*)data)[i];
        } else {
            ascii[i % 16] = '.';
        }
        if ((i+1) % 8 == 0 || i+1 == size) {
            printf(" ");
            if ((i+1) % 16 == 0) {
                printf("|  %s \n", ascii);
            } else if (i+1 == size) {
                ascii[(i+1) % 16] = '\0';
                if ((i+1) % 16 <= 8) {
                    printf(" ");
                }
                for (j = (i+1) % 16; j < 16; ++j) {
                    printf("   ");
                }
                printf("|  %s \n", ascii);
            }
        }
    }
}

You need to give the input as a buffer address and the size of the buffer, You can see the output like below您需要将输入作为缓冲区地址和缓冲区大小,您可以看到 output 如下所示

01 0F 30 36  20 32 35 33  32 20 34 34  31 33 20 31    ..06.2532.4413.1
37 02 05 01  A0 58 6A 59  06 01 00 30  08 10 00 00    7....XjY...0....
02 7C AB B6  67                                      .|..g

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM