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

标签 c linux file binary

首先,我正在 Linux 64 位上处理大型二进制文件 (2-4 GB),并且该文件也是从另一个进程映射的。因此,文件中的内容总是不断变化的。我想更改特定位/位置的一些位,但不必阅读它。

仅更改特定地址处的位,不关心其其余内容 附加编辑:或将位设置为始终卡住。 (该位无法更改)

当我使用hexdump读取它时,看起来是这样的。

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

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

最佳答案

对于 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函数,¶7):

When a file is opened with update mode ('+' as the second or third character in the above list of mode argument values), both input and output may be performed on the associated stream. However, output shall not be directly followed by input without an intervening call to the fflush function or to a file positioning function (fseek, fsetpos, or rewind), and input shall not be directly followed by output without an intervening call to a file positioning function, unless the input operation encounters end of file.

如果您希望确保该位已设置,请将分配替换为:

        c |= 1 << bitno;

如果您希望确保该位被重置,请将分配替换为:

        c &= ~(1 << bitno);

关于更改大型二进制文件中的特定位,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31579405/

相关文章:

c - 系统函数的返回值

c++ - gcc 优化

c - c语言中关于指针的问题

c - 如何只将最后 10 行写入 C 文件?

python - 将多个文件连接成一个文件对象而不创建新文件

c - 修改并返回指向结构体的指针

linux - 在 Linux 中通过网页进行一些管理工作的最佳方法(安全性)?

c++ - 套接字和文件推荐的缓冲区大小

java - 如何查找 Zip 文件目录中的任何文件

python - 以 "rock&roll"模式打开文件