#c #binary
#c #двоичный
Вопрос:
Я пытаюсь прочитать двоичный файл в следующем формате:
количество изображений [4-байтовый int]
width [4-байтовый int]
height [4-байтовый int]
данные в оттенках серого [ширина * высота в байтах]
(больше элементов того же типа)
Это первая вызываемая функция:
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)
}
Вот image
структура для тех, кому интересно:
struct image {
unsigned int width;
unsigned int height;
unsigned char *data;
};
И это то, что read_int_from_file
делает:
static unsigned int read_int_from_file(FILE *file) {
unsigned char chars[4];
if (fread(amp;chars, sizeof(char), 4, file) != 4) {
fprintf(stderr, "Couldn't read enough bytes!n");
return 0;
}
//Calculations follow that return right numbers
return out;
}
Это остальное:
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);
}
}
Проблема в том, что указатель на файл иногда перемещается вперед, когда он не должен этого делать, т. Е. Я нажимаю ftell(file) != expected_position
. Я получаю это после большого количества успешных чтений, но также и за некоторое время до конца.
У кого-нибудь есть какие-либо идеи, почему это может быть? Я имею в виду, даже если цифры были неправильными, этого не должно было произойти, не так ли? Спасибо!
Ответ №1:
Последовательности конца строки MS-DOS — это возврат каретки, новая строка ( CR NL
, 0x0D, 0x0A
), а Unix использует просто новую строку ( NL
или 0x0A
).
Измените строку
FILE *input_file = fopen(filename, "r");
Для
FILE *input_file = fopen(filename, "rb");
В противном случае, fread()
функция, используемая для перевода CR NL
как NL
, в системах Unix до стандарта POSIX «IEEE Std 1003.1-1988».
В MS-DOS, Windows и производных от них это переводится NL
как CR NL
.
Из-за этих переводов ваше мнение о позиции файла отличается от ftell()
вычислений.
Комментарии:
1. Это сделало это. Спасибо! Очень глупо с моей стороны забывать, что это может быть так.
2. Я не понимаю ваш предпоследний абзац. В Unix абсолютно никакого перевода не происходит, поскольку стандарт POSIX требует, чтобы текстовый режим вел себя идентично двоичному режиму.
3. Спасибо за обновление. Я использую
open()
вместоfopen()
с 1988 года.4. Провел 3 дня, задаваясь вопросом, почему это не работает, и не смог понять, что я забыл добавить ‘b’ в fopen. Большое спасибо.
Ответ №2:
Вам нужно открыть двоичный файл как таковой:
// v
FILE *input_file = fopen(filename, "rb");