简体   繁体   English

C中的十六进制转储文本和二进制文件

[英]Hexdump text and binary files in C

I am writing a code in C performing hexdump in both text and binary files. 我正在用C语言编写文本和二进制文件中的十六进制转储代码。 My output in text files are correct but when I tried performing hexdump in a binary file, I got garbages. 我在文本文件中的输出是正确的,但是当我尝试在二进制文件中执行hexdump时,出现了垃圾。 I would like to ask for your help if which part of my code is wrong and how should I correct my mistakes. 如果我的代码的哪一部分是错误的,我该如何纠正我的错误,我想向您寻求帮助。 Thanks. 谢谢。

#include <stdio.h>
#define OFFSET 16

main(int argc, char const *argv[]) 
{
    FILE *fp;
    char buff[OFFSET];
    int read;
    int address = 0;
    int i;

    if (argc != 2){
        exit(0);
    }

    fp = fopen(argv[1], "rb");

    while ((read = fread(buff, 1, sizeof buff, fp)) > 0){
        printf("%08x ", address);
        address += OFFSET;

        //print hex values 
        for (i = 0; i < OFFSET; i++){

            if(i >= read){
                buff[i] = 0;
            }
            if(buff[i] >= 33 && buff[i] <= 255 || buff[i] != 00){
                printf("%02x ", buff[i]);
            }
            if(buff[i] == 00){
                printf("   ");
            }
        }

        //print ascii values
        for (i = 0; i < OFFSET; i++) {
            printf("%c", (buff[i] >= 33 && buff[i] <= 255 ? buff[i] : ' '));
        }
        printf("\n");
    }

    fclose(fp);
}

You have a couple of errors in logic. 您在逻辑上有两个错误。 First as specified in the comment, all characters are equally important within a binary file. 首先,如注释中所指定,二进制文件中的所有字符都同等重要。 There is no need (and you shouldn't) test if(buff[i] >= 33 && buff[i] <= 255 || buff[i] != 00) for your binary output. 不需要(也不应该if(buff[i] >= 33 && buff[i] <= 255 || buff[i] != 00)对二进制输出测试if(buff[i] >= 33 && buff[i] <= 255 || buff[i] != 00)

The proper declarations for main are int main (void) and int main (int argc, char **argv) (which you will see written with the equivalent char *argv[] ). main的正确声明是int main (void)int main (int argc, char **argv) (您将看到使用等效的char *argv[]编写)。 See: C11 Standard §5.1.2.2.1 Program startup p1 (draft n1570) . 请参阅: C11标准§5.1.2.2.1程序启动p1(草稿n1570) See also: See What should main() return in C and C++? 另请参见: 请参见main()在C和C ++中应该返回什么?

Next with your binary output, you are attempting to print an unsigned value with %02x , but your are passing a signed character. 接下来是二进制输出,您尝试使用%02x打印无符号值,但是您正在传递带符号的字符。 If the char value is negative, you are trying to output the sign-extended value with outputs the full width of the unsigned value ( 02x will pad the field to 2 characters, but does not prevent more than two characters from printing). 如果char值为负,则您尝试输出带符号扩展值,并输出无符号值的完整宽度( 02x会将字段填充为2个字符,但不会阻止打印两个以上的字符)。 You have a couple of options, first use the hh length modifier to limit the type to 1-byte, and second simply cast the value to (unsigned char) , eg 您有两种选择,首先使用hh length修饰符将类型限制为1个字节,然后仅将值(unsigned char)(unsigned char) ,例如

            printf("%02hhx ", (unsigned char)buff[i]);

You logic is also a bit cumbersome. 您的逻辑也有点麻烦。 You should use if ... else if ... else to handle your binary cases. 您应该使用if ... else if ... else来处理二进制情况。 Further, you are outputting two spaces when either i >= read || buff[i] == 0 此外,当i >= read || buff[i] == 0时,您将输出两个空格。 i >= read || buff[i] == 0 , so you may as well combine the test. i >= read || buff[i] == 0 ,所以您最好将测试结合起来。

A short rewrite could look something like the following (which will read from the file given as the 1st argument -- or from stdin if no argument is given) 简短的重写可能类似于以下内容(它将从作为第一个参数给出的文件中读取-如果没有给出参数,则将从stdin读取)

#include <stdio.h>

#define OFFSET 16

int main (int argc, char const *argv[]) 
{
    char buff[OFFSET] = "";
    int read, address = 0, i;
    FILE *fp = argc > 1 ? fopen (argv[1], "rb") : stdin;

    if (!fp) {
        perror ("fopen");
        return 1;
    }

    while ((read = fread(buff, 1, sizeof buff, fp)) > 0) {
        printf("%08x ", address);
        address += OFFSET;

        for (i = 0; i < OFFSET; i++)    /* print hex values */
            if (i >= read || buff[i] == 0)
                printf("   ");
            else
                printf("%02hhx ", (unsigned char)buff[i]);

        fputs ("| ", stdout); /* optional separator before ASCII */

        for (i = 0; i < OFFSET; i++)    /* print ascii values */
            printf("%c", (buff[i] >= ' ' && buff[i] <= '~' ? buff[i] : ' '));
        putchar ('\n'); /* use putchar to output single character */
    }

    if (fp != stdin)
        fclose (fp);
}

(note: if your compiler does not support the hh prefix, the cast itself will suffice) (注意:如果您的编译器不支持hh前缀,则强制转换本身就足够了)

Look things over and let me know if you have further questions. 仔细检查一下,如果您还有其他问题,请告诉我。

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

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