fread(); problem in implementation

Asked

Viewed 232 times

4

I have a simple problem. I can use the function fread normally to work with audio processing in C. In case I have 2 codes. The first reads a file . WAV (with fread) and saved in a .CSV. file This step is working properly as I have already checked . csv with Matlab. However, in the second code when I try to open the file . CSV only returns junk from memory. So I created a file . txt with only 1 number and tried to access it through the function fread and yet it returns garbage.

Follows the code:

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

int main(){

    FILE *fp;
    //Este arquivo contem apenas o digito 1.
    fp = fopen("ex.txt","r");
    int text[100];

    fread(text, sizeof(text),1,fp);

    printf("%d",text[0]);

    fclose(fp);

    return 0;
}

What would be the main problem? I know the other methods like fgets and fscanf but I would like to use the fread.

1 answer

8


Your program has several small problems and you seem to have the right idea, but with implementation problems for a lower level language like C.

Initially, let’s make it clear that the function fread reads consecutive bytes of the stream you specified and then puts those bytes read "binary" in the memory you specify.

Note that here, fread nay interprets/converts the textual representation of numbers (for example, the string of characters 1) to the "internal" form of the computer (the binary representation of it, which may be big or little-endian).

If your file ex.txt has solely and exclusively the digit 1 in the text form, which will be in the file will be (most likely, encoded in latin1 or UTF-8) a single byte and the function fread will read this byte (for the character 1 the internal representation, with these encodings I spoke of, will be 49 (the value "ASCII" of 1)) and will place the content of that byte in the address memory &text (is not mistake the &).

On "popular" computers (Arms, Powerpcs, i386, amd64 etc.), an integer has 4 bytes size and therefore when you read the memory position text[0] to print with printf, you will be reading the number 1 and 3 other bytes that may be some junk.

(Also, most of the computers we have at our disposal are little-endian).

On my computer (running Debian GNU/Linux testing, with GCC 8.2.1 and C glibc library 2.28), if I put a file ex.txt with digit 1 followed by new-line (i.e., '\n', which has ASCII code 10) and I run your program, I get the number 2609, which makes complete sense, since 2609 = 49 + 10 * 256 and this is consistent with the computer being little-endian:

  • first, byte number 49 is in memory
  • then byte number 10 is in memory

(Most likely, zeros were placed on the rest of the memory set aside for text in my system, but you can’t count on that).

Your code still has some other problems (besides indentation/spacing), but one of the main ones is that you declare the vector text as a vector of ints, but seems to want to put arbitrary data (binaries), if you insist on using fgets (fscanf or fgets would interpret the character sequences for the internal representation of the computer).

Assuming you still want to use the binary sequence in your manipulations, you should, after reading the data as you have already done:

  • read the memory region text with a pointer to chars
  • use the format string %c in the printf
  • declare the vector text as just of chars (not strictly necessary, but avoids a large amount of "sambadas" with pointers)

Honestly, it’s simpler to use fgets (generally, more secure than other options) and let fread just for when you want the binary file data.

  • Thank you so much for the explanation! That’s exactly what I needed to understand.

  • @Gabriellavoura, it’s a pleasure. I edited my answer to put some links to Wikipedia that give more information/context to anyone who reads the answer.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.