首先,我在Linux 64bit上使用大型二进制文件(2-4 GB),此文件也从另一个进程映射。因此,文件中的内容始终会发生变化。我想在特定的位/位置改变一些,但不必阅读它。
只需更改特定地址的位,而不关心其余内容 额外编辑:或将位设置为始终被卡住。 (该位无法更改)
当我使用hexdump来阅读它时,它似乎就是这样。
3ffbd280 00 00 78 32 fb 44 22 cc 44 11 22 aa b2 33 b2 c3
任何想法或想法都非常受欢迎。
答案 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
,fsetpos
或rewind
),输入不得直接跟随没有输出的输出 干预调用文件定位功能,除非输入操作遇到文件结尾。
如果您希望确保设置该位,请将赋值替换为:
c |= 1 << bitno;
如果您希望确保该位复位,请将指定替换为:
c &= ~(1 << bitno);