1

i am currently trying to read .BMP files using C++, but somehow after reading a few bytes the end of the file is reached (fgetc() returns -1). I've reduced the problem to a minimal example:

#include <iostream>

int main()
{
    // Open file
    FILE* file = fopen("C:/Path/to/file", "r");

    // Get and print file size in bytes
    fseek(file, 0L, SEEK_END);
    std::cout << ftell(file) << std::endl;
    rewind(file);

    int byte, i = 0;
    do
    {
        // Get each byte
        byte = fgetc(file);
        // Print i and value of byte
        std::cout << i << ", " << byte << std::endl;
        i++;
    }
    // Stop reading when end of file is reached
    while (byte != EOF);

    std::cin.get();

    return 0;
}

When using this to read .BMP files (problem does not occur on simple formats like .txt files), It reads the file length correctly, but finds the EOF way before reaching the end of the file.

For example, using this file, it reads a file length of 120054, but fgetc() returns -1 at i=253.

What exactly am i doing wrong, and how can i fix this problem?

  • 1
    Since you're using C++ it's very odd to be using the C `fopen` type methods. Streams can do everything you've done here. – tadman Jan 03 '18 at 15:51
  • Possible duplicate of [Why is fread reaching the EOF early?](https://stackoverflow.com/questions/164002/why-is-fread-reaching-the-eof-early) – underscore_d Jan 03 '18 at 16:03

2 Answers2

4

Reading a file in plain "r" mode on DOS/Windows may treat ASCII 26 (^Z) as "end of file". It may also convert line endings from CR LF (13 10) to LF (10), which you also don't want.

Looking at your sample file, I do indeed see that character (it's 1A in hex):

0000340 0c 1f 15 0e 1f 15 0e 1f 14 10 1f 14 10 21 17 10
0000360 21 17 10 22 18 11 23 19 12 25 19 13 26[1a]14 26

The position is 375 octal, which is 253 decimal. Sound familiar? :)

Use "rb":

FILE* file = fopen("C:/Path/to/file", "rb");
davmac
  • 20,150
  • 1
  • 40
  • 68
2

Change

FILE* file = fopen("C:/Path/to/file", "r");

to

FILE* file = fopen("C:/Path/to/file", "rb");

to read the file in binary mode. That usually helps to avoid such strange errors.

Anton Malyshev
  • 8,686
  • 2
  • 27
  • 45
  • its always these simple, subtle mistakes that can drive you up the wall, thanks for the help. I'll accept the answer as soon as i can. – sFyX67v7Ia1XDGFU Jan 03 '18 at 15:53