【问题标题】:Write a file bit by bit一点一点地写一个文件
【发布时间】:2017-10-08 21:58:39
【问题描述】:

基本上我正在尝试读取一个文件,更改每个 4 位序列的最后一位,然后读取更改后的文件并将其恢复为原始文件。 es test1.bin -> test2.bin -> test3.bin 00011100 -> 00001101 -> 00011100 但是,虽然第二个文件没问题,但第三个文件每 8 次而不是 4 次更改一次。这是

int main(int argc, char** argv) {   
    ifstream f("C:\\Users\\simon\\Desktop\\test\\test.bin", ios::binary | ios::in);
    ofstream f_o("C:\\Users\\simon\\Desktop\\test\\test2.bin", ios::binary | ios::out);
    char c,app;

    int rund=0;
    while (f.get(c)){
        app=c;
        for (int i = 7; i >= 0; i--){
            if(rund==3){ //it's the 4th bit, I change it
                rund=0;
                if(((c >> i) & 1) == 0)  app |= 1 << i; //if it's 0 i change to 1
                else  app |= 0 << i;
                }   
            else  rund += 1;
        }
        f_o.put(app); 
    }

    f.close();
    f_o.close();

    ifstream f2("C:\\Users\\simon\\Desktop\\test\\test2.bin", ios::binary | ios::in);
    ofstream f_o2("C:\\Users\\simon\\Desktop\\test\\test3.bin", ios::binary | ios::out);

    rund=0;
    while (f2.get(c)){
        app=c;
        for (int i = 7; i >= 0; i--){ 
            if(rund==3){
                rund=0;
                if(((c >> i) & 1) == 0)  app |= 1 << i;
                else  app |= 0 << i;
                } 
            else  rund += 1;     
        }
        f_o2.put(app); 
    }

}

【问题讨论】:

  • 将您的问题缩小到更具体的问题。这称为“调试”。
  • 是的。使用称为“调试”的技术将您的问题缩小到更具体的问题。您生成的 minimal reproducible example 应该有 4-8 行(但仍然是一个完整的 C++ 程序)。不过,在您需要在此处发布相关问题之前,制作此 MCVE 的行为将向您揭示问题的可能性是好的。这是目的的一部分。
  • 你为什么不直接使用c2 ^= 0x11;
  • 正在帮助你;你只是还不知道。 :)
  • @alteration 这是一个按位异或运算,花点时间理解它会将该代码的长度减少....bignum%。使用异或,您可以翻转这些位 1) 而不循环它们,以及 2) 使用相同的操作,无论该位当前是 1 还是 0(使用 xor 您可以“翻转”位的状态)。

标签: c++ file binary fstream


【解决方案1】:

KIIV 已经有效地为您提供了(非常简单的)解决方案,所以我将展示它并解释它的工作原理(我无法抗拒,这里的代码减少太漂亮了,我我并不羞于承认我和 xor 有过恋情。)

新代码:

int main(int argc, char** argv) {   
    ifstream f("C:\\Users\\simon\\Desktop\\test\\test.bin", ios::binary | ios::in);
    ofstream f_o("C:\\Users\\simon\\Desktop\\test\\test2.bin", ios::binary | ios::out);
    char c;

    while (f.get(c))
        f_o.put(c ^ 0x11);

    f.close();
    f_o.close();

    ifstream f2("C:\\Users\\simon\\Desktop\\test\\test2.bin", ios::binary | ios::in);
    ofstream f_o2("C:\\Users\\simon\\Desktop\\test\\test3.bin", ios::binary | ios::out);

    while (f2.get(c))
        f_o2.put(c ^ 0x11);   
}

按位异或 (XOR)

运算符 ^ 执行按位异或运算,即“异或”运算。它按位(按位!)工作,如下所示:

0 ^ 0 -> 0
0 ^ 1 -> 1
1 ^ 0 -> 1
1 ^ 1 -> 0

换句话说,A ^ B 为 1,如果 A、B 中只有一个为 1。因此是“异或”。

使用 ^ 进行位翻转

Xor 是一个非常有趣的按位运算。除了其他有趣的属性,当您需要“翻转”位的状态(即,将 1 映射到 0 或 0 到 1)时,它是完美的工具。

假设我接受A ^ 1。如果 A 为 0,那么我有 0 ^ 1 = 1。如果 A 为 1,那么我有 1 ^ 1 = 0。所以你看,如果我用 1 异或位,我有效地“翻转”了位。

OTOH,假设我接受A ^ 0。如果 A 为 0,那么我有 0 ^ 0 = 0。如果 A 为 1,那么我有 1 ^ 0 = 1。换句话说,A ^ 0 = A!

这是一个完美的情况...我们可以构造一个位串与您的字节进行异或,并且该位串中的每个位将确定您的字节中的相应位是否被翻转!

0x11

剩下的唯一要了解的是如何创建翻转所需位所需的值。您想翻转第 4 位和第 8 位。所以我们需要构造00010001。如果你知道十六进制,很明显这是0x11。如果没有,请使用在线转换器,然后在完成此项目后去学习十六进制..voila :)

【讨论】:

  • 非常完整详尽的解释,谢谢先生
猜你喜欢
  • 1970-01-01
  • 2019-07-25
  • 2023-04-02
  • 2010-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-21
  • 1970-01-01
相关资源
最近更新 更多