5

I am currently trying to read 256 bytes from a binary file and not getting any output (or errors) when running my program. I am a little confused where I am going wrong on this. Attempting to read each byte as a char and store as a char array of length 256. I have reviewed similar questions on SO already and haven't had any luck so far. Simplified version of my code below:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]){
    FILE *binary = fopen(argv[1], "rb");
    char bytesFromBinary[256];

    fread(&bytesFromBinary, 1, 256, binary);
    printf("%s", bytesFromBinary);
    return 0;
}
GregH
  • 5,125
  • 8
  • 55
  • 109
  • 9
    You're trying to read *binary* and then print it using a *string* format specifier. What output do you expect if that binary data starts with a null byte or the bytes are all non-printable values? Or what happens if those bytes *don't* contain a null terminator to tell `printf` where it stops? – Ken White Apr 04 '16 at 01:18
  • 1
    Iterating through your array and printing each value of the array as a number should help you see what is in the array because it will not interpret extended or restricted ASCII characters, but as integer values. – callyalater Apr 04 '16 at 01:31
  • What are the actual contents of the file? Can you post a snippet? – Fiddling Bits Apr 04 '16 at 01:37
  • It is just a .bin file. Cannot open and see anything meaningful even in notepad++ – GregH Apr 04 '16 at 01:39
  • 3
    Why do you expect `printf` to print something meaningful then? – user253751 Apr 04 '16 at 01:57

3 Answers3

5

A basic use of fread will check the return against the number of bytes expected to validate you read what you intended to read. Saving the return allows you to handle partial reads as well.

The following minimal example reads 16-bytes at a time from the file given as the first argument (or stdin by default if no file is given) into buf and then outputs each value to stdout in hex-format.

#include <stdio.h>

#define BUFSZ 16

int main (int argc, char **argv) {

    unsigned char buf[BUFSZ] = {0};
    size_t bytes = 0, i, readsz = sizeof buf;
    FILE *fp = argc > 1 ? fopen (argv[1], "rb") : stdin;

    if (!fp) {
        fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
        return 1;
    }

    /* read/output BUFSZ bytes at a time */
    while ((bytes = fread (buf, sizeof *buf, readsz, fp)) == readsz) {
        for (i = 0; i < readsz; i++)
            printf (" 0x%02x", buf[i]);
        putchar ('\n');
    }
    for (i = 0; i < bytes; i++) /* output final partial buf */
        printf (" 0x%02x", buf[i]);
    putchar ('\n');

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

    return 0;
}

(note: bytes == readsz only when the size parameter to fread is 1. The return is the number of items read and each item is only equal to 1 for char type values)

Example Use/Output

$ echo "A quick brown fox jumps over the lazy dog" | ./bin/fread_write_hex
 0x41 0x20 0x71 0x75 0x69 0x63 0x6b 0x20 0x62 0x72 0x6f 0x77 0x6e 0x20 0x66 0x6f
 0x78 0x20 0x6a 0x75 0x6d 0x70 0x73 0x20 0x6f 0x76 0x65 0x72 0x20 0x74 0x68 0x65
 0x20 0x6c 0x61 0x7a 0x79 0x20 0x64 0x6f 0x67 0x0a

Look over the example and let me know if you have any questions.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
0

You have not declared a long enough variable.

Your declaration char bytesFromBinary[256]; reserves 256 bytes, and fread fills all 256 bytes. There is no trailing '\0' and there is no space for it, so whatever happens to be next in memory gets overwritten/destroyed. That already will result in all kind of random errors and crashes.

Then, in printf, you try to print it, and the function will keep running through memory until it happens to encounter a '\0' to stop it, so if the program makes it there, you would get a printout of memory, maybe short, maybe thousands of (non-printable) characters long.

You need to declare the variable always one longer, to have space for the trailing '\0': char bytesFromBinary[257];. even better is to use sizeof(var)-1 in fread, or use a constant for the desired length and declare it with +1.

Aganju
  • 6,295
  • 1
  • 12
  • 23
-1

It fails because you are trying printing a block of bytes as a C-style string.

There are two kinds of files: binary file and text file. To read/write a file, you should open it in the corresponding mode.

If your file is created in this way:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    FILE *binary = fopen("file.txt", "wbx");
    if(!binary)
    {
        perror("fopen()");
        exit(EXIT_FAILURE);
    }
    char bytesToBinary[256] = ":-)";

    fwrite(bytesToBinary, 1, 256, binary);
    fclose(binary);
    return 0;
}

Your code should be successful.

nalzok
  • 14,965
  • 21
  • 72
  • 139
  • i am opening in binary mode as it is a binary file. Not sure what you are saying to fix here – GregH Apr 04 '16 at 01:36
  • binary means 'non-printable characters'. If you try to print them anyway, you will get strange behavior. – Aganju Apr 04 '16 at 01:39
  • The problem here is *not* that it's not opened in binary mode. – user253751 Apr 04 '16 at 01:58
  • Also, there *aren't* two kinds of file, on any operating system I've encountered. Text files are files that happen to contain ASCII (or Unicode) characters, and binary files are files that don't. – user253751 Apr 04 '16 at 01:58
  • @immibis If you write a C-style string to a binary file by `fwrite()`, and then read it out by `fread()`, that string will remain unchanged. Thus OP's code will work as he expect. – nalzok Apr 04 '16 at 03:08
  • @immibis Do you mean `fread()` and `fwrite()` behave same no matter the file is opened in binary mode or text mode? – nalzok Apr 04 '16 at 03:09
  • @sunqingyao No, I mean that the asker is **already** opening their file in binary mode, and it's not working regardless. – user253751 Apr 04 '16 at 04:35
  • @sunqingyao And for the second comment, I mean exactly what I said. I did not mean anything to do with text or binary mode. – user253751 Apr 04 '16 at 04:35
  • @immibis I suspect that the file to be read is a **text file** – nalzok Apr 04 '16 at 04:51