我需要打开现有文件并写到该文件的任意位置。也位于可能大于文件当前大小的位置。
使用“ab”打开文件会在每次调用写入操作时将位置指示器设置为文件末尾 - 这样就无法工作。
使用“w + b”或“wb”打开文件会导致文件被多次写入(复制?)。 Filesize从0开始多次 - 这需要很长时间。观看执行以下测试(1次运行)时会发生什么的视频:http://screencast.com/t/Uj5ymikZUYJ
BOOST_AUTO_TEST_CASE(FileWriteTest_W_PLUS_B) {
auto started = chrono::high_resolution_clock::now();
FILE *filePointer = nullptr;
auto tmpFilename = string("C:\\temp\\") + boost::uuids::to_string(boost::uuids::random_generator()());
auto bufferSize = 1024 * 1024;
unique_ptr<unsigned char[]> buffer(new unsigned char[bufferSize]);
RAND_bytes(buffer.get(), bufferSize);
for (long long i = 0; i < 5; i++) {
//Open file
int openError = fopen_s(&filePointer, tmpFilename.c_str(), "w+b");
if (openError != 0)
BOOST_FAIL(string("Failed to open file ") + tmpFilename);
auto CurrentPosition = 1024LL * 1024LL * 1024LL * i;
//Set position to 0/1/2/3/4 GB
fsetpos(filePointer, &CurrentPosition);
//Write 1 GB of data at current position
for (int n = 0; n < 1024; n++) {
int written = fwrite(buffer.get(), sizeof(unsigned char), bufferSize, filePointer);
if (written != bufferSize) {
BOOST_FAIL(string("Unable to write ") + to_string(bufferSize) + string(" to file ") + tmpFilename + string(" at position ") + to_string(CurrentPosition));
}
}
//Close file
fclose(filePointer);
}
auto ended = chrono::high_resolution_clock::now();
cout << "Time :" << duration_cast<duration<double>>(ended - started).count() << " seconds";
}
所以我的问题是:有没有办法打开现有文件并写入任意位置(也在大于当前大小的位置) - 没有得到我目前使用的性能损失“wb” / “w + b”
或者我是否必须将文件设为最终大小 - 我第一次写文件? (例如Torrent客户似乎这样做。)
由于I / O性能不佳,fstream不是一种选择。 (见writing-a-binary-file-in-c-very-fast)
答案 0 :(得分:3)
您应该以{{1}}模式打开流。 "r+b"
模式会导致文件被截断。如果该文件不存在,则必须首先使用"w"
创建该文件。
但请注意,"wb"
可能无法将当前位置设置为超出文件末尾。如果需要,您应该检查返回值并将文件填充到目标位置。
对于作为字节偏移有意义的位置,流也必须以fsetpos()
的二进制模式打开。默认情况下,流更多地以文本打开,在某些系统(如Windows)上可能会阻止正确的偏移管理。
答案 1 :(得分:0)
我建议您手动跟踪文件大小,如果大小太小,请使用以下内容:
fseek(f, 0, SEEK_END);
int pos = ftell(f);
while (pos < wantedsize) {
fputc(0, f); ++pos;
}
请注意,文件超过~2GB会出现问题。