开发者

Reading a binary file in C: ftell returns results that sometimes are off by one

开发者 https://www.devze.com 2023-03-10 00:51 出处:网络
I\'m trying to read a binary file that is in the following format: number of images [4-byte int] width [4-byte int]

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 开发者_JAVA百科(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!


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.


You need to open the binary file as such:

//                                   v
FILE *input_file = fopen(filename, "rb");
0

精彩评论

暂无评论...
验证码 换一张
取 消