更改大型二进制文件中的特定位

时间:2015-07-23 06:11:07

标签: c linux file binary

首先,我在Linux 64bit上使用大型二进制文件(2-4 GB),此文件也从另一个进程映射。因此,文件中的内容始终会发生变化。我想在特定的位/位置改变一些,但不必阅读它。

只需更改特定地址的位,而不关心其余内容 额外编辑:或将位设置为始终被卡住。 (该位无法更改)

当我使用hexdump来阅读它时,它似乎就是这样。

3ffbd280  00 00 78 32 fb 44 22 cc  44 11 22 aa b2 33 b2 c3

任何想法或想法都非常受欢迎。

2 个答案:

答案 0 :(得分:1)

FILE* fp = fopen( "bigfile.abc", "rb+" )  
//rb+ is important! see here: the wrong mode may clear/delete the file.
//http://www.cplusplus.com/reference/cstdio/fopen/?kw=fopen

if( fp ) 
{
    unsigned char b = 0;
    fseek( fp, #_of_bytes_from_origin, SEEK_SET )
    fread( &b, 1, 1, fp );      //read 1 unit of 1 byte into 'b'

    b ^= (1<<bit_index);        //toggle the bit, as Jonathan said

    fseek( fp, -1, SEEK_CUR );  //go one byte backwards (you went forwards when reading)
    fwrite( &b, 1, 1, fp );     //write 1 unit of 1 byte back into the file
    fclose(fp);                 //close the file when done
}

这是我多年来在32位计算机上使用C的经验,但我并不认为以上任何一种都会在64位架构上发生变化,因为您和#39;重新明确一个字节

请参阅:http://www.cplusplus.com/reference/cstdio/ 和核心文件函数:fopen(),fclose(),fseek(),ftell(),fread(),fwrite()

更改特定位:

byte_to_change &= ~(1<<bit_index)

其中bit_index为0到7.这会将该位设置为0。

byte_to_change |= (1<<bit_index)

将其设置为1。

答案 1 :(得分:1)

对于64位Linux,fseek()的签名不会造成麻烦; offset参数是long,这意味着它将是64位数量,并且可以轻松处理2-4 GiB文件。如果问题出在32位Linux或64位Windows上,那么故事就会有所不同。处理2 GiB和4 GiB之间的偏移时会遇到问题。

假设打开文件流进行读写。假设通过文件中的绝对字节偏移加上位号(0 ... 7)来指定位位置。假设该位应该改变,因此操作将位从1切换到0或从0切换到1.假设不需要保留文件中当前位置的记录,以便在翻转位之后可以恢复它。然后操作顺序可能是:

void flip_bit(FILE *fp, long offset, int bitno)
{
    int c;
    assert(fp != 0);
    assert(offset >= 0);
    assert(bitno >= 0 && bitno < 8);

    fseek(fp, offset, SEEK_SET);
    if ((c = getc(fp)) != EOF)
    {
        c ^= 1 << bitno;
        fseek(fp, -1L, SEEK_CUR);  // Step backwards 1 byte
        putc(c, fp);
        fflush(fp);
    }
}

您更改的每个假设都会触发代码中的相应更改。 fflush(fp);必须最大化在磁盘上进行更改的机会,以便其他进程看到它。此外,fflush(fp)意味着即使没有介入搜索也可以安全地使用流进行输入(或输出)(ISO / IEC 9899:2011§7.21.5.3 fopen函数< / strong>,¶7):

  

以更新模式打开文件时('+'作为第二个或第三个字符)   在上面的模式参数值列表中,输入和输出都可以在上面执行   相关流。但是,如果没有输入,输出不应直接输入   干预调用fflush函数或文件定位函数(fseek,   fsetposrewind),输入不得直接跟随没有输出的输出   干预调用文件定位功能,除非输入操作遇到文件结尾。

如果您希望确保设置该位,请将赋值替换为:

        c |= 1 << bitno;

如果您希望确保该位复位,请将指定替换为:

        c &= ~(1 << bitno);