如何在C ++中减小fstream文件的大小

时间:2018-10-26 07:09:49

标签: c++ fstream filesize

在C ++ 11中切断fstream文件结尾的最佳方法是什么

我正在编写一个数据持久性类来存储音频编辑器的音频。我选择使用fstream(可能是个坏主意)来创建随机访问二进制读写文件。

每次我在文件中录制一些声音时,我都会将其粘贴到该文件的末尾。另一个内部数据结构/文件,包含指向音频文件的指针并跟踪编辑。
当我撤消录音动作然后执行其他操作时,音频文件的最后一位变得无关紧要。在文档的当前状态中未引用它,并且您无法将自己重做回到可以再次看到它的状态。因此,我想将文件的这一部分切掉,并从新的一端开始录制。我不需要在中间切掉咬痕,只需在末端切掉。

当用户退出时,此文件将保留并在他们再次打开项目时重新加载。

在我的应用程序中,我希望用户一直这样做,并且能够执行此操作可能会为我节省多达30%的文件大小。该文件将很长,可能非常长,因此,每次发生这种情况时,将其重写为另一个文件都不可行。

可以选择在用户保存时重写它,但是它仍然没有那么吸引人。

我可以在开头添加一个值,说该文件应该保留多长时间,然后覆盖末尾以回收空间,但同时。如果我想在发生崩溃的情况下不断更新数据存储文件,这意味着我将一遍又一遍地重写开始。我担心这可能对闪存驱动器不利。通过分析指针文件,我还可以重新计算负载文件的有用部分的结尾,但与此同时,我可能会浪费所有空间,这很复杂。

在fstream API中是否对此有一个简单的调用?

我使用了错误的库吗?注意,我想坚持使用我喜欢的通用STL,这样我就可以使代码尽可能地跨平台。

我似乎无法在文档中找到它,并且已经浏览了许多小时。这不是地球的尽头,但会使它变得更简单,更有效。也许我只是以某种方式想念它。

感谢您的帮助 安德烈’

2 个答案:

答案 0 :(得分:4)

  

fstream API中是否对此有一个简单的调用?

如果您具有C ++ 17编译器,请使用std::filesystem::resize_file。在以前的标准中,标准库中没有这样的东西。

对于较早的编译器...在Windows上,您可以使用SetFilePoinerSetFilePoinerEx将当前位置设置为所需的大小,然后调用SetEndOfFile。在Unix上,您可以使用truncateftruncate。如果您需要可移植的代码,则可以使用Boost.Filesystem。将来最容易从它迁移到RESOURCE_ID,因为std::filesystem主要是基于它指定的。

答案 1 :(得分:0)

如果您有包含文件中当前位置的变量,则可以找回“不需要的块”的长度,然后继续从那里开始写。

// Somewhere in the begining of your code:
std::ofstream *file = new std::ofstream();
file->open("/home/user/my-audio/my-file.dat");
// ...... long story of writing data .......

// Lets say, we are on a one millin byte now (in the file)
int current_file_pos = 1000000;
// Your last chunk size:
int last_chunk_size = 12345;
// Your chunk, that you are saving
char *last_chunk = get_audio_chunk_to_save();
// Writing chunk
file->write(last_chunk, last_chunk_size);
// Moving pointer:
current_file_pos += last_chunk_size;
// Lets undo it now!
current_file_pos -= last_chunk_size;
file->seekp(current_file_pos);
// Now you can write new chunks from the place, where you were before writing and unding the last one!
// .....
// When you want to finally write file to disk, you just close it
file->close();
// And when, truncate it to the size of current_file_pos
truncate("/home/user/my-audio/my-file.dat", current_file_pos);

不幸的是,您必须编写一个跨平台函数 truncate ,该函数将在Windows中调用SetEndOfFile,在Linux中调用truncate。使用预处理器宏很容易。