Побитовое чтение бинарного файла

Я знаю функцию ниже:

size_t fread(void *ptr, size_t size_of_elements, size_t number_of_elements, FILE *a_file);

Он читает только байт за байтом, моя цель - иметь возможность читать 12 бит за раз, а затем помещать их в массив. Любая помощь или указатели будут очень признательны!


person Ryan    schedule 27.07.2012    source источник
comment
Извините, один байт за раз — это наименьшая степень детализации, которую вы можете сделать. Вам придется прибегнуть к (содроганию) реального программирования, чтобы разделить 12-битные объекты.   -  person Hot Licks    schedule 27.07.2012
comment
Я думаю, вам нужен этот ответ: stackoverflow.com /вопросы/141525/   -  person Jessedc    schedule 27.07.2012


Ответы (6)


Добавляя к первому комментарию, вы можете попробовать читать по одному байту за раз (объявить переменную char и писать туда), а затем использовать побитовые операторы >> и ‹‹ для чтения побитно. Подробнее читайте здесь: http://www.cprogramming.com/tutorial/bitwise_operators.html

person Carlos Vergara    schedule 27.07.2012
comment
это то, что я буду делать, я дам вам знать, как это работает! Большое спасибо!! Это наверное выход!! - person Ryan; 29.07.2012

Я реализовал несколько методов для чтения/записи файлов по крупицам. Вот они. Будет ли это жизнеспособным или нет для вашего варианта использования, вы должны решить это для себя. Я пытался сделать максимально читаемый оптимизированный код, какой только мог, не будучи опытным разработчиком C (пока).

Внутри он использует «bitCursor» для хранения информации о предыдущих битах, которые еще не соответствуют полному байту. В нем есть поля данных who: d хранит данные, а s хранит размер или количество битов, хранящихся в курсоре.

У вас есть четыре функции:

  • newBitCursor(), который возвращает объект bitCursor со значениями по умолчанию
    {0,0}. Такой курсор необходим в начале последовательности операций чтения/записи в файл или из файла.
  • fwriteb(void *ptr, size_t sizeb, size_t rSizeb, FILE *fp, bitCursor *c), который записывает крайние правые биты sizeb значения, хранящегося в ptr, в fp.
  • fcloseb(FILE *fp, bitCursor *c), который записывает оставшийся байт, если предыдущая запись не полностью инкапсулировала все данные, которые необходимо записать, это, вероятно, почти всегда так...
  • freadb(void *ptr, size_t sizeb, size_t rSizeb, FILE *fp, bitCursor *c), который считывает биты sizeb и выполняет побитовое ИЛИ их преобразование в *ptr. (поэтому вы несете ответственность за инициализацию *ptr как 0)

Дополнительная информация представлена ​​в комментариях. Повеселись!

Изменить: мне стало известно сегодня, когда я сделал это, я принял Little Endian! :Р Ой! Всегда приятно осознавать, какой я все еще нуб ;D.

Изменить: дескрипторы двоичных файлов GNU .

person quirinpa    schedule 30.03.2016

Много лет назад я написал несколько процедур ввода-вывода на C для кодировщика Хаффмана. Это должно иметь возможность читать и записывать биты, а не байты. Я создал функции, аналогичные read(2) и write(2), которые можно попросить (скажем) прочитать 13 бит из потока. Например, для кодирования байты будут подаваться в кодер, а переменное количество битов будет выходить с другой стороны. У меня была простая структура с битовым указателем на текущий считываемый или записываемый байт. Каждый раз, когда он заканчивался, он сбрасывал завершенный байт и сбрасывал указатель на ноль. К сожалению, этого кода давно нет, но, возможно, стоит разобрать кодер Хаффмана с открытым исходным кодом и посмотреть, как там решается проблема. Точно так же кодирование base64 берет 3 байта данных и превращает их в 4 (или наоборот).

person David G    schedule 27.07.2012
comment
В каждой библиотеке сжатия есть что-то подобное. Тот, что в ffmpeg/libavutil, выглядит многоразовым. - person Alan Curry; 27.07.2012

Прочитайте первые два байта из указателя файла a_file и проверьте биты в младшем или старшем байте — в зависимости от порядка байтов. вашей платформы (x86 имеет обратный порядок байтов) — с помощью операторов битового сдвига.

Вы не можете поместить биты в массив, так как для битов нет типа данных. Вместо того, чтобы хранить 1 и 0 в массиве, что неэффективно, дешевле просто хранить два байта в двухэлементном массиве (скажем, типа unsigned char *) и писать функции для сопоставления этих двух байтов с одним из 4096 (2). ^12) представляющие интерес ценности.

В качестве сложности, при последующих чтениях, если вы хотите fread проходить по указателю через каждые 12 бит, вы будете читать только один байт, используя оставшиеся биты от предыдущего чтения для построения новых 12-бит. битовое значение. Если нет остатков, вам нужно будет прочитать два байта.

Ваши функции сопоставления должны будут учитывать второй случай, когда биты использовались из предыдущего чтения, потому что для двух байтов потребуется другое сопоставление. Чтобы сделать это эффективно, можно использовать модуль счетчика чтения для переключения между двумя отображениями.

person Alex Reynolds    schedule 27.07.2012

прочитайте 2 байта и выполните побитовые операции, чтобы сделать это в следующий раз, прочитайте 2-й байт и далее, примените побитовые операции, которые вернутся, как вы ожидали. . . .

person sunmoon    schedule 27.07.2012

Для вашей проблемы вы можете увидеть эту демонстрационную программу, которая читает 2 байта, но фактическая информация составляет всего 12 бит. Помимо этого, используется побитовый доступ.

fwrite() — это функция стандартной библиотеки, которая принимает аргумент размера в виде байта и имеет тип int. Таким образом, невозможно точное 12-битное чтение. Если файл, который вы создаете, создайте, как показано ниже, а также прочитайте как ниже это решит вашу проблему.

Если этот файл является специальным файлом, который не был написан вами, то следуйте стандарту, предусмотренному для чтения этого файла. Я думаю, что они также пишут только так. Или вы можете предоставить точную информацию, где я могу вам помочь.

#include<stdio.h>
#include<stdlib.h>
struct node
 {
   int data:12;

 }NODE;
int main()
{
   FILE *fp;
   fp=fopen("t","w");
   NODE.data=1024;
   printf("%d\n",NODE.data);
   fwrite(&NODE,sizeof(NODE),1,fp);
   NODE.data=0;
   NODE.data=2048;
   printf("%d\n",(unsigned)NODE.data);
   fwrite(&NODE,sizeof(NODE),1,fp);
   fclose(fp);
   fp=fopen("t","r");
   fread(&NODE,sizeof(NODE),1,fp);
   printf("%d\n",NODE.data);
   fread(&NODE,sizeof(NODE),1,fp);
   printf("%d\n",NODE.data);
   fclose(fp);
}
person rajesh6115    schedule 28.07.2012