C语言 C 编程:如何从二进制文件中读取和打印一个字节?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2028457/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 04:06:34  来源:igfitidea点击:

C Programming : how do I read and print out a byte from a binary file?

c

提问by Esquif

I wish to open a binary file, to read the first byte of the file and finally to print the hex value (in string format) to stdout (ie, if the first byte is 03 hex, I wish to print out 0x03 for example). The output I get does not correspond with what I know to be in my sample binary, so I am wondering if someone can help with this.

我希望打开一个二进制文件,读取文件的第一个字节,最后将十六进制值(以字符串格式)打印到标准输出(即,如果第一个字节是 03 十六进制,我希望打印出 0x03 例如) . 我得到的输出与我所知道的示例二进制文件中的内容不一致,所以我想知道是否有人可以帮助解决这个问题。

Here is the code:

这是代码:

#include <stdio.h>
#include <fcntl.h>

int main(int argc, char* argv[])
{
int fd;
char raw_buf[1],str_buf[1];

fd = open(argv[1],O_RDONLY|O_BINARY);

    /* Position at beginning */
lseek(fd,0,SEEK_SET);

    /* Read one byte */
read(fd,raw_buf,1);

    /* Convert to string format */
sprintf(str_buf,"0x%x",raw_buf);
printf("str_buf= <%s>\n",str_buf);

close (fd);
return 0;   
}

The program is compiled as follows:

程序编译如下:

gcc rd_byte.c -o rd_byte

gcc rd_byte.c -o rd_byte

and run as follows:

并运行如下:

rd_byte BINFILE.bin

rd_byte BINFILE.bin

Knowing that the sample binary file used has 03 as its first byte, I get the output:

知道使用的示例二进制文件的第一个字节是 03,我得到了输出:

str_buf= <0x22cce3>

str_buf= <0x22cce3>

What I expect is str_buf= <0x03>

我期望的是 str_buf= <0x03>

Where is the error in my code?

我的代码中的错误在哪里?

Thank you for any help.

感谢您的任何帮助。

回答by Nick Meyer

You're printing the value of the pointer raw_buf, not the memory at that location:

您正在打印 pointer 的值raw_buf,而不是该位置的内存:

sprintf(str_buf,"0x%x",raw_buf[0]);

As Andreas said, str_bufis also not big enough. But: no need for a second buffer, you could just call printfdirectly.

正如安德烈亚斯所说,str_buf还不够大。但是:不需要第二个缓冲区,您可以直接调用printf

printf("0x%x",raw_buf[0]);

回答by Diego Torres Milano

Less is more...

少即是多...

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

int main(int argc, char* argv[]) {
    int fd;
    unsigned char c;

    /* needs error checking */
    fd = open(argv[1], O_RDONLY);
    read(fd, &c, sizeof(c));
    close(fd);

    printf("<0x%x>\n", c);
    return 0;
}
  1. seeking is not needed
  2. if you want to read a byte use an unsigned char
  3. printfwill do the format
  1. seeking 不需要
  2. 如果你想读取一个字节使用 unsigned char
  3. printf会做格式

回答by CB Bailey

I think that you are overcomplicating things and using non-portable constructs where they aren't really necessary.

我认为您使事情过于复杂,并在不必要的地方使用了不可移植的结构。

You should be able to just do:

你应该能够做到:

#include <stdio.h>

int main(int argc, char** argv)
{
    if (argc < 2)
        return 1; /* TODO: better error handling */

    FILE* f = fopen(argv[1], "rb");

    /* TODO: check f is not NULL */

    /* Read one byte */    
    int first = fgetc(f);

    if (first != EOF)
        printf("first byte = %x\n", (unsigned)first);

    /* TODO else read failed, empty file?? */

    fclose(f);

    return 0;
}

回答by Thomas Bonini

str_bufhas a maximum size of 1 (char str_buf[1];), it should at least 5 bytes long (4 for XxXX plus the \0).

str_buf最大大小为 1 ( char str_buf[1];),它应该至少有 5 个字节长(4 表示 XxXX 加上 \0)。

Moreover, change

此外,改变

sprintf(str_buf,"0x%x",raw_buf);

to

sprintf(str_buf,"0x%x",*raw_buf);

otherwise you'll print the address of the raw_bufpointer, instead of its value (that you obtain by dereferencingthe pointer).

否则,您将打印raw_buf指针的地址,而不是其值(通过取消引用指针获得)。

Finally, make sure both raw_buf is unsigned. The standard specified that the signness of chars (where not explicitly specified) is implementation defined, ie, every implementation decides whether they should be signed or not. In practice, on most implementations they are signed by default unless you're compiling with a particular flag. When dealing with bytes always make sure they are unsigned; otherwise you'll get surprising results should you want to convert them to integers.

最后,确保两个 raw_buf 都是unsigned. 该标准规定字符的符号(没有明确指定)是实现定义的,即每个实现决定它们是否应该被签名。实际上,在大多数实现中,除非您使用特定标志进行编译,否则默认情况下它们是签名的。在处理字节时,始终确保它们是无符号的;否则,如果您想将它们转换为整数,您会得到令人惊讶的结果。

回答by Esquif

Using the information from the various responses above (thank you all!) I would like to post this piece of code which is a trimmed down version of what I finally used.

使用上面各种回复中的信息(谢谢大家!)我想发布这段代码,它是我最终使用的精简版本。

There is however a difference between what the following code does and what was described in my origal question : this code does not read the first byte of the binary file header as described originally, but instead reads the 11th and 12th bytes (offsets 10 & 11) of the input binary file (a .DBF file). The 11th and 12th bytes contain the length of a data record (this is what I want to know in fact) with the Least Significant Byte positioned first: for example, if the 11th and 12th bytes are respectivly : 0x06 0x08, then the length of a data record would be 0x0806 bytes, or 2054bytes in decimal

但是,以下代码的作用与我的原始问题中描述的内容之间存在差异:此代码不会像最初描述的那样读取二进制文件头的第一个字节,而是读取第 11 个和第 12 个字节(偏移量 10 和 11 ) 的输入二进制文件(.DBF 文件)。第 11 和 12 字节包含一条数据记录的长度(这实际上是我想知道的),最低有效字节在前:例如,如果第 11 和第 12 字节分别为:0x06 0x08,则长度为数据记录将为 0x0806 字节,或十进制 2054 字节

 #include <stdio.h>
 #include <fcntl.h>

 int main(int argc, char* argv[]) {
 int fd, dec;
 unsigned char c[1];
 unsigned char hex_buf[6];

 /* No error checking, etc. done here for brevity */

 /* Open the file given as the input argument */
 fd = open(argv[1], O_RDONLY);

 /* Position ourselves on the 11th byte aka offset 10 of the input file */
 lseek(fd,10,SEEK_SET);

 /* read 2 bytes into memory location c */
 read(fd, &c, 2*sizeof(c));

 /* write the data at c to the buffer hex_buf in the required (reverse) byte order + formatted */
 sprintf(hex_buf,"%.2x%.2x",c[1],c[0]);
 printf("Hexadecimal value:<0x%s>\n", hex_buf);

 /* copy the hex data in hex_buf to memory location dec, formatting it into decimal */
 sscanf(hex_buf, "%x", &dec);

 printf("Answer: Size of a data record=<%u>\n", dec);

 return 0;

}

}