Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Read file byte by byte using C

Tags:

c

hex

byte

I am trying to read a file byte by byte then print it out using C, but the output doesn't match the display of the hex editor.

In hex editor the first 2 lines look like this:

0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0111 1111 1000 0000 0000

expected output:

00000000000000000000000000000000
00000000000001111111100000000000

but when my code outputs this:

00000000000000000000001111111100
00000000000000000000000000000000

here's my code:

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

int main() {
    FILE *fp;
    unsigned char buffer[4900] = "";
    int y;

    y = 0;
    fp = fopen("tugasz.ksa", "rb");

    for (int x = 0; x < 4900; x++) {
        fread(buffer, 1, 4900, fp);
        printf("%x", buffer[x]);
    }
    return (0);
}
like image 795
Neios Flame Stuxnet Avatar asked Aug 15 '26 11:08

Neios Flame Stuxnet


2 Answers

There a multiple problems in your code:

  • You do not test for fopen failure, causing undefined behavior if the file does not exist or cannot be open.
  • You are not reading the file byte by byte, instead you are reading blocks of 4900 bytes and just print one byte of each block.
  • You probably hit the end of file very quickly, but you do not test for end of file, so the output may come from the same part of the file. A classic case of one bug hiding another bug.
  • The conversion format %x outputs 1 or 2 characters per byte depending on the byte value. This is a problem is the file contents are 0x00, 0x01, 0x10 and 0x11, which respectively produce 0, 1, 10 and 11, hence the apparent misaligned input.
  • For cleanliness, you should fclose the stream.
  • From the data posted, it is unclear if the hex editor is displaying data in hexadecimal or binary format and whether the values are word based or byte based.

Here is a simpler approach:

#include <stdio.h>

int main() {
    FILE *fp;
    int c, i, max;

    fp = fopen("tugasz.ksa", "rb");
    if (fp == NULL) {
        fprintf(stderr, "cannot open input file\n");
        return 1;
    }
    for (i = 0, max = 4900; i < max && (c = getc(fp)) != EOF; i++) {
        printf("%02x", c);
        if (i % 16 == 15)
            putchar('\n');  // 16 bytes per line
        else if (i % 2 == 1)
            putchar(' ');   // group bytes in pairs
    }
    if (i % 16 != 0)
        putchar('\n');  // output a newline if needed

    fclose(fp);
    return 0;
}
like image 187
chqrlie Avatar answered Aug 17 '26 03:08

chqrlie


for(int x = 0; x<4900; x++) {
   fread(buffer, 1, 4900, fp);
   printf("%x", buffer[x]);
}

In the first iteration of the loop, this will print only the first character in buffer at index 0.

In the second iteration, this will print the the second character in buffer at index 1.

So if your file is less than 4900 bytes, it prints only 1 character. The reason you get more output is because the loop doesn't break when you reach end of file. It's printing mostly garbage, not the actual file content.

Given the hex-decimal view of your input file, and the expectation that the output is all 0 and 1, it is unlikely that the source file is a collection of bytes consisting of 0 and 1. Instead, it likely contains bytes from 0 to 256, and each byte is a collection of 0 and 1 bits. Print it as follows:

int main(void)
{
    FILE *fp = fopen("tugasz.ksa", "rb");
    if(fp)
    {
        unsigned char buffer[4096];
        size_t sz;
        int line = 0;
        while ((sz = fread(buffer, 1, sizeof(buffer), fp)) > 0)
        {
            for(int i = 0; i < sz; i++)
            {
                //print the bits of the byte, at buffer[i]:
                for(int j = 0; j < 8; j++)
                {
                    int mask = 1 << (7 - j);
                    int bit = buffer[i] & mask;
                    printf("%d", bit ? 1 : 0);
                }

                //add new line for every 4 byte
                line++;
                if((line % 4) == 0)
                    printf("\n");
            }
        }
    }

    return 0;
}

If bytes are 0 and 1, then simply print it as printf("%d", buffer[i]) or printf("%02X", buffer[i]) for byte values:

int main(void)
{
    FILE *fp = fopen("tugasz.ksa", "rb");
    if(fp)
    {
        unsigned char buffer[4096];
        size_t sz;
        while((sz = fread(buffer, 1, sizeof(buffer), fp)) > 0)
        {
            for(int i = 0; i < sz; i++)
                printf("%d", buffer[i]);
                //or use "%02X" instead, for printing the byte values:
                //printf("%02X ", buffer[i]);
        }
    }
    return 0;
}
like image 34
Barmak Shemirani Avatar answered Aug 17 '26 03:08

Barmak Shemirani



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!