我想替换二进制文件中的某些部分(中间)。如果我使用ostream out("file.bin",ios::binary)
,它将删除旧文件并创建一个新文件。但是,如果我使用fstream out("file.bin",ios::binary|ios::in|ios::out)
,seekp()
将无法到达正确的位置,tellp()
将始终返回-1。那么有没有办法替换文件中的某些部分?
提前谢谢。
答案 0 :(得分:4)
您必须使用结尾, in 和 out 位设置打开流:
std::fstream out("file.bin", ios::binary | ios_base::ate);
这会阻止您的文件在打开时重置;然后,使用seekp
和unformatted 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() == false
或off != 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);