开发者

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

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开发者_StackOverflow sample binary, so I am wondering if someone can help with this.

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

and run as follows:

rd_byte BINFILE.bin

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

str_buf= <0x22cce3>

What I expect is str_buf= <0x03>

Where is the error in my code?

Thank you for any help.


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

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

As Andreas said, str_buf is also not big enough. But: no need for a second buffer, you could just call printf directly.

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


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. printf will do the format


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


str_buf has a maximum size of 1 (char str_buf[1];), it should at least 5 bytes long (4 for XxXX plus the \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_buf pointer, instead of its value (that you obtain by dereferencing the pointer).

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.


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

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

}

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜