Как все говорили, в C. нет доступных функций доступа к битам.
Если говорить более подробно, диск является блочным устройством , означающим, что доступ к его содержимому разрешен только для чтения и записи фрагментов с четко определенными размерами, которые по историческим причинам обычно имеют размер 512 байт. .
Итак, как работают функции, которые позволяют вам обращаться к одному char
за раз (учтите, что char
в C - это наименьшая единица данных, а в некоторых системах она может отличаться от 8 бит, то есть 12 или 16 бит)?
Стандартная библиотека C и почти все функции файлов ОС используют механизм буферизации, чтобы позволить вам получить доступ к одному char
. Система считывает порцию данных с диска и доставляет вам один байт из порции и т. Д. До последнего char
порции. При следующем запросе пользователя на char
функция считывает следующий фрагмент файла с диска, буферизует его внутренне и предоставляет пользователю самый первый char
из только что прочитанных данных записи.
Этот процесс продолжается до достижения конца файла.
Тот же процесс, но в обратном порядке, выполняется, когда записывает данных на диск char
за один раз. Каждый char
буферизуется, и при достижении размера фрагмента он сбрасывается на физический диск.
Чтобы решить вашу проблему, вы должны написать свой собственный набор функций буферизации, который будет считывать char
за раз из файла и выводить один бит за раз для каждого запроса. Когда исчерпана полная разрядность char
, функция считывает другой символ и запускается снова.
Это небольшой пример такого набора функций:
#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;
}