【问题标题】:How to reduce the size of a fstream file in C++如何在 C++ 中减小 fstream 文件的大小
【发布时间】:2018-10-26 07:09:48
【问题描述】:

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

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

每次我将一点声音录制到我的文件中时,我都会简单地将其添加到该文件的末尾。另一个内部数据结构/文件,包含指向音频文件的指针并跟踪编辑。
当我撤消录制操作然后执行其他操作时,音频文件的最后一位变得无关紧要。它在文档的当前状态中没有被引用,您无法将自己重做回您可以再次看到它的状态。所以我想把这部分文件剪掉,然后在新的一端开始录制。我不需要剪掉中间的部分,就在最后。

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

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

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

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

在 fstream API 中有一个简单的调用吗?

我是否使用了错误的库?请注意,我想坚持使用我喜欢的通用 STL,因此我可以使代码尽可能跨平台。

我似乎无法在文档中找到它,并且已经查找了好几个小时。这不是地球的尽头,但会使它变得更简单,并且可能更有效。也许我只是想念它。

感谢您的帮助 安德烈'

【问题讨论】:

    标签: c++ fstream filesize


    【解决方案1】:

    在 fstream API 中有对此的简单调用吗?

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

    使用较旧的编译器...在 Windows 上,您可以使用 SetFilePointerSetFilePointerEx 将当前位置设置为您想要的大小,然后调用 SetEndOfFile。在 Unix 上,您可以使用 truncateftruncate。如果你想要可移植的代码,那么你可以使用Boost.Filesystem。从以后最简单的迁移到std::filesystem,因为std::filesystem大多是基于它指定的。

    【讨论】:

    • 谢谢!不幸的是,我还在 11 岁,但现在我有动力去 17 岁,感谢 17 岁的标准礼让,为我提供了我需要的东西。
    【解决方案2】:

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

    // 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。使用预处理器宏很容易。

    【讨论】:

    • 是的,因为我还在 11 岁,这就是我认为我必须做的事情。大多数时候这不会是一个问题。
    猜你喜欢
    • 1970-01-01
    • 2011-01-25
    • 2013-07-15
    • 1970-01-01
    • 2010-10-23
    • 1970-01-01
    • 1970-01-01
    • 2021-11-25
    • 1970-01-01
    相关资源
    最近更新 更多