Чтение двоичного файла по 1 байт за раз
Я пытаюсь читать двоичный файл в байтах C 1 за один раз и после нескольких часов работы в Интернете я все равно не могу получить его, чтобы извлечь что-либо, кроме мусора и/или сбоя seg. В основном двоичный файл находится в формате списка, длина которого составляет 256 элементов, а каждый элемент - 1 байт (без знака int от 0 до 255). Я пытаюсь использовать fseek и fread, чтобы перейти к "индексу" в двоичном файле и получить это значение. Код, который у меня есть:
unsigned int buffer;
int index = 3; // any index value
size_t indexOffset = 256 * index;
fseek(file, indexOffset, SEEK_SET);
fread(&buffer, 256, 1, file);
printf("%d\n", buffer);
Прямо сейчас этот код дает мне случайные номера мусора и сегрегацию. Любые советы о том, как я могу заставить это работать правильно?
Ответы
Ответ 1
В вашем коде вы пытаетесь прочитать 256 байтов по адресу одного int. Если вы хотите читать по одному байту за раз, вызовите fread(&buffer, 1, 1, file);
(см. fread).
Но более простым решением будет объявить массив байтов, прочитать все вместе и обработать его после этого.
Ответ 2
Ваши запутанные байты с int. Общим термином для байта является unsigned char. Большинство байтов имеют ширину 8 бит. Если данные, которые вы читаете, составляют 8 бит, вам необходимо прочитать в 8 бит:
#define BUFFER_SIZE 256
unsigned char buffer[BUFFER_SIZE];
/* Read in 256 8-bit numbers into the buffer */
size_t bytes_read = 0;
bytes_read = fread(buffer, sizeof(unsigned char), BUFFER_SIZE, file_ptr);
// Note: sizeof(unsigned char) is for emphasis
Причиной считывания всех данных в память является сохранение потока ввода-вывода. При каждом запросе на вход есть накладные расходы, независимо от запрашиваемого количества. Наихудший вариант - чтение одного байта за раз или поиск одной позиции за раз.
Ниже приведен пример служебных данных, необходимых для чтения 1 байта:
Tell OS to read from the file.
OS searches to find the file location.
OS tells disk drive to power up.
OS waits for disk drive to get up to speed.
OS tells disk drive to position to the correct track and sector.
-->OS tells disk to read one byte and put into drive buffer.
OS fetches data from drive buffer.
Disk spins down to a stop.
OS returns 1 byte to your program.
В вашем проекте программы вышеуказанные шаги будут повторяться 256 раз. Со всеми предложениями строка с надписью "- > " будет читать 256 байт. Таким образом, служебные данные выполняются только один раз, а не 256 раз, чтобы получить такое же количество данных.
Ответ 3
unsigned char buffer; // note: 1 byte
fread(&buffer, 1, 1, file);
Настало время читать ман, которому я верю.
Ответ 4
Вы пытаетесь прочитать 256 байтов в 4-байтную целочисленную переменную, называемую "buffer". Вы переписываете следующие 252 байта других данных.
Кажется, что buffer
должен быть либо unsigned char buffer[256];
, или вы должны делать fread(&buffer, 1, 1, f)
, и в этом случае buffer
должен быть unsigned char buffer;
.
В качестве альтернативы, если вам нужен только один символ, вы можете просто оставить buffer
как int
(unsigned не требуется, потому что C99 гарантирует разумный минимальный диапазон для простого int) и просто скажите:
buffer = fgetc(f);
Ответ 5
Пара проблем с кодом в его нынешнем виде.
Прототип для fread:
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
Вы задали размер 256 (байты) и число до 1. Это прекрасно, что означает "читать один кусок в 256 байт, засунуть его в буфер".
Однако ваш буфер имеет длину порядка 2-8 байтов (или, по крайней мере, значительно меньше 256 байт), поэтому у вас есть переполнение буфера. Вероятно, вы хотите использовать fred (& buffer, 1, 1, file).
Кроме того, вы записываете данные байта в указатель int. Это будет работать на одной конечности (по сути, на самом деле), так что вы будете в порядке над архитектурой Intel и от того, что узнаете плохие привычки, которые вернутся и укусят вас на днях.
Попробуйте реально записывать байтовые данные в байтовое хранилище, а не в ints или float.