在ios :: in和out模式下打开文件时,fstream seekp()无法正常工作

时间:2015-12-14 11:38:35

标签: c++

我想替换二进制文件中的某些部分(中间)。如果我使用ostream out("file.bin",ios::binary),它将删除旧文件并创建一个新文件。但是,如果我使用fstream out("file.bin",ios::binary|ios::in|ios::out)seekp()将无法到达正确的位置,tellp()将始终返回-1。那么有没有办法替换文件中的某些部分?

提前谢谢。

2 个答案:

答案 0 :(得分:4)

您必须使用结尾 in out 位设置打开流:

std::fstream out("file.bin", ios::binary | ios_base::ate);

这会阻止您的文件在打开时重置;然后,使用seekpunformatted output函数,您可以在中间编辑它。

此示例输出stackovstrlow,显示如何将所有步骤链接在一起:

#include <fstream>
#include <string>
#include <vector>
#include <iostream>

int main()
{
    // create the bin file
    {
        std::string str("stackoverflow\n");
        std::ofstream file("file.bin", std::ios_base::binary);
        file.write(str.c_str(), str.length() + 1);
    }
    // edit the bin file "in the middle"
    {
        std::fstream file("file.bin", std::ios_base::in | std::ios_base::out | std::ios_base::ate);
        file.seekp(7);
        file.write("str", 3);
    }
    // read and see what we've done
    std::ifstream file("file.bin", std::ios_base::binary);
    std::vector<char> v(14);
    file.read(v.data(), 14);
    std::string str(v.cbegin(), v.cend());
    std::cout << str;
}

答案 1 :(得分:2)

寻找文件流应该可以工作,但并非总是如此。值得注意的是,如果imbue() ed std::locale()使用的编码是可变宽度,则搜索失败。引自27.9.1.5 [filebuf.virtuals]第13段:

  

效果:让width表示a_codecvt.encoding()。如果is_open() == falseoff != 0 && width <= 0,则定位操作失败。 ...

假设文件已打开OK,则表示使用了带有非固定宽度编码的std::locale。避免此问题的方法是在打开文件之前使用C语言环境。例如:

std::fstream stream;
stream.imbue(std::locale::classic());
stream.open("file.bin", std::ios_base::binary | std::ios_base::in | std::ios_base::out);