C как читать в одном бите из файла
Я читаю в двоичном файле в C: infile=fopen(input, "rb")
и пытаюсь прочитать каждый бит по одному, так что если бы содержимое файла было:
"привет"
Значение ascii 'h' равно 104
, поэтому в двоичном виде оно будет 1101000
.
Существует ли метод fgetbit (), который можно вызвать и назначить примитивному типу? Пример:
int my_bit=fgetbit(infile); //value of my_bit would be 1 for hello example.
3 ответа:
Вы не можете получить более детализированный, чем байт во время ввода-вывода файла, но если вы действительно хотите работать на уровне битов, вы можете использовать битовую маску или битовый сдвиг, чтобы изолировать биты, которые вы хотите, как только вы прочитаете байты из файла.
Например, для вывода / проверки каждого отдельного бита в байте:
#include <limits.h> // for CHAR_BIT ... unsigned char b = 0xA5; // replace with whatever you've read out of your file for(i = 0; i < CHAR_BIT; i++) { printf("%d", (b>>i)&1); }
Чтобы выделить наиболее значимый бит в байте:
unsigned char mask = 0x80; // this value may differ depending on your system's CHAR_BIT unsigned char value = /* read from file */; if(value&mask) { // MSB is set } else { // MSB is clear }
Вы можете просто прочитать файл в двоичном формате:
FILE *fp; fp = fopen(input, "rb");
И затем, вы можете получить отдельные биты, используя что-то вроде этого:
bool getBit(unsigned char byte, int position) // position can be 0-7 { return (byte >> position) & 0x1; }
Как все вам говорили, в C.{[12] нет функций доступа к битам.]} Если говорить более подробно, то диск является блокирующим устройством , что означает, что доступ к его содержимому разрешен только для чтения и записи фрагментов хорошо определенных размеров, которые по историческим причинам обычно составляют 512 байт.
Итак, как работают функции, которые позволяют получить доступ к одному
Стандартная библиотека C и почти все файловые функции ОС используют механизм буферизации, позволяющий получить доступ к одному файлуchar
за один раз (рассмотрим, чтоchar
в C является наименьшей единицей данных, и на некоторых системах это может быть отличается от 8 бит, то есть 12 или 16 бит)?char
. Система считывает фрагмент данных с диска и передает вам один байт из фрагмента, и так далее до последнегоchar
фрагмента. При следующем запросе пользователя наchar
функция считывает следующий фрагмент файла с диска, буферизует его внутри и предоставляет пользователю самый первыйchar
из только что прочитанной записи данные.Этот процесс продолжается до достижения конца файла.
Тот же процесс, но в обратном порядке, выполняется при записи данных на диск a
char
одновременно. Каждыйchar
буферизуется, и когда размер куска достигнут, он сбрасывается на физический диск.Чтобы решить вашу проблему, вы должны написать свой собственный набор буферных функций, которые будут читать
char
одновременно из файла и выводить один бит за раз для каждого запроса. При полной разрядности изchar
exausted функция прочитает другой символ и начнет снова.Это небольшой пример такого набора функций:
#include <stdio.h> #include <limits.h> /* * Bit FILE pointer structure */ typedef struct { FILE *fp; //Disk file pointer int ReadChar; //Current char read from stream int BitCounter; //counter of the current bit } BITFILE; /* * Function to open a file for bit reading */ BITFILE *bfopen(const char *filename) { FILE *fp = fopen(filename, "rb"); if (!fp) //Error opening file return NULL; BITFILE *bf = malloc(sizeof(BITFILE)); if (!bf) //No memory { fclose(fp); //Close file return NULL; } bf->fp = fp; //Save File pointer bf->ReadChar = getc(fp); //Read in first char bf->BitCounter = 0; //First bit return bf; } /* * Function to close (release) a bit file */ void bfclose(BITFILE *bf) { if (!bf) //Bad descriptor // Do some error signaling return; fclose(bf->fp); //Close file free(bf); //release memory } /* * Function to read a single bit */ int fgetbit(BITFILE *bf) { if (!bf) //Bad descriptor // Do some error signaling return; if (bf->BitCounter >= CHAR_BIT) //No more bits to read on this machine { bf->ReadChar = getc(bf->fp); //Read in another char bf->BitCounter = 0; //Reset counter } if (EOF == bf->ReadChar) //If end of file reached return EOF return EOF; //Note that to avoid sign complications in bit working // we cast the value to unsigned int bit = ((unsigned)bf->ReadChar) & 1; //Get the LSB that we will return bf->ReadChar = ((unsigned)bf->ReadChar) >> 1; //Advance bits shifting bf->BitCounter++; //Update counter return bit; } int main(int argc, char *argv[]) { BITFILE *bf = bfopen("test.txt"); if (!bf) { printf("Error can't open file \"%s\"\n", "test.txt"); return 1; } for (int cnt=1; ; cnt++) { int bit = fgetbit(bf); if (EOF == bit) break; printf ("%3d) bit %d\n", cnt, bit); } bfclose(bf); return 0; }