C如何从文件中读取一个位

时间:2018-05-08 02:15:29

标签: c binary bit-manipulation fgets

我正在C:infile=fopen(input, "rb")中读取二进制文件,并尝试一次读取每个位,所以如果文件内容是:

“你好”

'h'的ascii值是104所以在二进制中它是1101000

是否有一个fgetbit()方法可以调用并分配给基本类型? EX:

int my_bit=fgetbit(infile); //value of my_bit would be 1 for hello example.

3 个答案:

答案 0 :(得分:8)

在文件I / O期间,您不能比字节更精细,但如果您真的想在位级工作,可以使用位掩码或位移来隔离您想要的位你有从文件中读出的字节。

例如,输出/检查字节中的每个位:

#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
}

答案 1 :(得分:2)

您只需阅读Binary中的文件:

FILE *fp;
fp = fopen(input, "rb");

然后,您可以使用以下内容获取单个位:

bool getBit(unsigned char byte, int position) // position can be 0-7
{
    return (byte >> position) & 0x1;
}

答案 2 :(得分:2)

正如大家告诉你的那样,C中没有可用的位访问功能。

更详细地说,磁盘是一个块设备,这意味着只允许读取和写入定义明确的维度的块来访问其内容,出于历史原因,这些块通常为512字节大。

那么如何使用允许您一次访问单个char的函数(考虑到C中的char是最小的数据单元,并且在某些系统上它可以与8位不同,即12或16位)?

C标准库和几乎所有OS文件函数都使用缓冲机制来访问单个char。系统从磁盘读取一大块数据并从块传递给您一个字节,依此类推,直到块的最后char。在char的下一个用户请求中,该函数从磁盘读取下一个文件块,在内部对其进行缓冲,并向用户提供刚刚读取的新记录数据char

此过程一直持续到达文件的末尾。

同样的过程,但以相反的方式,一次数据到磁盘a 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;
}