Reputation: 12616
I'm trying to read a binary file that is in the following format:
number of images [4-byte int]
width [4-byte int]
height [4-byte int]
grayscale data [width * height bytes]
(more elements of the same type)
That's the first function being called:
int process_file(const char *filename) {
FILE *input_file = fopen(filename, "r");
//Get number of images
unsigned int number_of_images = read_int_from_file(input_file);
//Allocate memory for all images
struct image *images = malloc(sizeof(struct image) * number_of_images);
read_images(images, number_of_images, input_file)
}
Here's the image
structure for anyone wondering:
struct image {
unsigned int width;
unsigned int height;
unsigned char *data;
};
And that's what read_int_from_file
does:
static unsigned int read_int_from_file(FILE *file) {
unsigned char chars[4];
if (fread(&chars, sizeof(char), 4, file) != 4) {
fprintf(stderr, "Couldn't read enough bytes!\n");
return 0;
}
//Calculations follow that return right numbers
return out;
}
That's the rest:
static int read_images(struct image *images, unsigned int number_of_images, FILE * file) {
struct image *current_image = images;
int i;
for (i = 0; i < number_of_images; i++) {
read_image(current_image++, file)
}
return EXIT_SUCCESS;
}
static int read_image(struct image *image, FILE *file) {
static long int expected_position = 4;
if (ftell(file) != expected_position) {
fprintf(stderr, "Reading @ %lu when should be @ %lu!",
ftell(file), expected_position);
exit(EXIT_FAILURE);
}
unsigned int width = read_int_from_file(file);
unsigned int height = read_int_from_file(file);
unsigned int size = width * height;
unsigned char *data = malloc(sizeof(char) * size);
if (data) {
if (fread(data, sizeof(char), size, file) != size) {
exit(EXIT_FAILURE);
}
image->width = width;
image->height = height;
image->data = data;
expected_position += 2 * 4 + width * height;
return EXIT_SUCCESS;
} else {
exit(EXIT_FAILURE);
}
}
The problem is that the file pointer is sometimes going ahead when it shouldn't do so, i.e. I'm hitting ftell(file) != expected_position
. I'm getting it after a good amount of successful reads, but some good time before the end, too.
Does anyone have any idea why that may be? I mean, even if the numbers were wrong, that shouldn't happen, should it? Thanks!
Upvotes: 0
Views: 1683
Reputation: 19467
MS-DOS end-of-line sequences are Carriage Return, New Line (CR NL
, 0x0D, 0x0A
), and Unix uses simply New Line (NL
or 0x0A
).
Change the line
FILE *input_file = fopen(filename, "r");
to
FILE *input_file = fopen(filename, "rb");
Otherwise, the fread()
function used to translate CR NL
as NL
, on Unix systems prior to POSIX standard "IEEE Std 1003.1-1988".
On MS-DOS, Windows and derivatives, it translates NL
as CR NL
.
These translations cause your opinion of the file position to differ from ftell()
's calculations.
Upvotes: 5
Reputation: 38183
You need to open the binary file as such:
// v
FILE *input_file = fopen(filename, "rb");
Upvotes: 4