Trying to understand fread
Asked Answered
M

2

5

I have a datafile.

#version 460 core
out vec4 FragColor;

void main()
{
    FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
}

And I am trying to read the contents of it with fread.

    FILE *fshader;
    char *fbuffer;
    long fsize;

    fshader = fopen("src/graphics/_fragment.shader", "r");

    fseek(fshader, 0L, SEEK_END); 
    fsize = ftell(fshader); 
    rewind(fshader);

    fbuffer = (char *)malloc(fsize + 1);
    fread(fbuffer, 1, fsize, fshader); 
    fbuffer[fsize] = '\0';

But I don't understand how fread works. It keeps reading 6 characters more than it should.

#version 460 core
out vec4 FragColor;

void main()
{
    FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
}_to_te
Myeloid answered 25/10, 2024 at 1:40 Comment(9)
"It keeps reading 6 characters more than it should" How do you know that if you're not looking at the return value of fread?Zeitgeist
@Zeitgeist - thx for reply. I am logging the result of fbuffer to terminal.Myeloid
Show how you are printing the result.Sylvestersylvia
@Mark Tolonen - I am using this, printf("%s\n", fbuffer); EDIT: I thought that fbuffer[fsize] = '\0'; adds a nul terminate to the end which is why I malloc +1 to size.Myeloid
You are likely on Windows. newlines are written to a file in text mode as \r\n but translated back to \n when read back. If you have 6 newlines, in text mode ftell no specified meaning and should only be used with fseek, but is likely the byte-offset of the end of the file before the \r\n are translated, so you'll put the nul 6 characters past the translated end of the text.Sylvestersylvia
@Mark Tolonen - thx man you were right. I switched the fopen mode to binary "rb" and it worked.Myeloid
You're reading text. Text mode is appropriate, but fread returns the characters read after text translation so just capture the return value and use it for nul-terminating the string.Sylvestersylvia
You may want to add the information on how you are printing the result to the question. Generally, the question itself should contain all important information. It should not be necessary to read the comments section in order to obtain all important information.Philan
fbuffer[fsize] = '\0'; writes a NULL to the end of the buffer, but not to the end of the read data. You have to analyze the result of fread().Heindrick
E
2

There are 2 possible solutions:

  1. Either specify that the file has a binary format (to save \r characters):
fshader = fopen("src/graphics/_fragment.shader", "rb");
  1. Either put the 0-terminator in the position obtained after reading (to ignore\r characters):
size_t _fsize;
_fsize = fread(fbuffer, 1, fsize, fshader);
fbuffer[_fsize] = '\0';
Ensue answered 25/10, 2024 at 2:23 Comment(1)
Thx Makarov, I figured it out from the other comments but I will set yours as the answer because you knew exactly what was wrong and provided code. Your #1 solution is what i did to fix it but I added #2 as well.Myeloid
P
5

My guess is that you are on Microsoft Windows and that the text file has \r\n line endings.

On Microsoft Windows, when reading the character combination \r\n in text mode, it will get translated to \n. However, when at the end of the file, ftell will give you the length of the file in untranslated bytes, even when in text mode. This means that as far as fread is concerned, your file has a length that is a few bytes shorter than reported by ftell.

For this reason, you should set the position of the terminating null character according to the number of bytes read by fread, by inspecting the return value of fread. You should not set it according to what ftell reported.

Philan answered 25/10, 2024 at 1:50 Comment(1)
Hey you were right man, ty. I switched the fopen mode to binary instead of text mode and it worked.Myeloid
E
2

There are 2 possible solutions:

  1. Either specify that the file has a binary format (to save \r characters):
fshader = fopen("src/graphics/_fragment.shader", "rb");
  1. Either put the 0-terminator in the position obtained after reading (to ignore\r characters):
size_t _fsize;
_fsize = fread(fbuffer, 1, fsize, fshader);
fbuffer[_fsize] = '\0';
Ensue answered 25/10, 2024 at 2:23 Comment(1)
Thx Makarov, I figured it out from the other comments but I will set yours as the answer because you knew exactly what was wrong and provided code. Your #1 solution is what i did to fix it but I added #2 as well.Myeloid

© 2022 - 2025 — McMap. All rights reserved.