2

我即将开始一个项目,我可以预见到有需要编辑的大文件(主要是平面文本文件,但可能是 CSV、固定宽度、XML 等)。我需要开发这些部件以在应用程序中进行此编辑。

在尝试确定一种处理编辑大量数据(可能进入 GB 范围)而无需加载整个数据的好方法时,我发现 Audacity 能够很好地处理大文件。Audacity 是开源的,所以我认为在这种情况下它对我来说是一个很好的教学工具。但是,我开始在循环中思考自己的代码,现在我完全糊涂了。

我希望这个问题有两个结果:

  1. 无需加载整个文件即可处理此编辑的好方法。我考虑在他们编辑数据时加载数据,按需缓存。

  2. 解释 Audacity 是如何做到的。

我正在使用 C# 和 .NET,但答案不需要与该环境耦合。

4

2 回答 2

3

一些技巧可以使编辑更简单、更快捷。

  1. 索引它以加快访问速度。 当用户什么都不做时,浏览文件并创建一个索引,以便您可以快速找到文件中的特定位置(见下文)。
  2. 仅存储用户所做的更改。 在用户保存之前,不要尝试将它们直接应用于文件。
  3. 设置用户跳转到某个点时读取内存的限制。最初读取一两个屏幕的数据以便显示它,然后如果用户没有立即跳转到新位置,则在当前位置之前和之后读取一点。

索引:

当用户想要跳转到第 X 行时间戳 T时,您不想浏览整个文件,计算换行符和字符。浏览数据并创建记录。比如说,每 50 行,记录字节偏移量、字符数和行号。这些数据可以存储在哈希表、树或只是一个有序列表中。然后当用户在文件中跳转时,您可以找到最近的索引点并从那里读取,直到找到请求的点。这种技术在使用 Unicode 时特别​​有用,其中每个字符的字节数可能会有所不同。如果文件太大,内存中无法容纳完整的索引,您可能希望限制索引点并将它们间隔得更宽,或者将索引存储在临时文件中。

编辑和更改大文件:

正如 Harvey 所建议的那样 - 仅将更改存储在内存中(作为差异),然后在通过从输入到输出的流式传输保存时将它们应用于文件。树或有序列表可能会有所帮助,因此您可以在从输入写入输出时快速找到下一个需要进行更改的地方。

如果更改太大而无法放入内存,您可能希望在单独的临时文件中跟踪它们(可能与原始文件位于同一文件夹中)。您可以继续编写一个连续的更改列表,并将新的更改附加到此更改文件中。保存时,您将通读更改列表并创建要应用的更改的最终列表,然后再删除临时文件。出于性能原因,避免重写更改日志文件可能会有所帮助;相反,只需附加到它的末尾,并在执行保存时删除多余的或取消的编辑。

有趣的事实:您用于更改日志的相同结构可用于提供撤消/重做信息。

于 2010-01-12T00:44:43.407 回答
2

声音文件基本上是一个数据流,对吧?因此,您实际上不需要一次处理整个文件。Audacity 用户在任何给定时刻只能使用该大文件的一小部分。

假设,如果您将 1 秒的声音片段添加到一个大声音文件中,您实际上只需要在必须保存时处理整个文件,此时您将 3 个部分拼接在一起:之前、1 秒片段和后。所以唯一真正需要在内存中的是 1 秒的片段,可能还有片段前后的一小部分声音。

因此,当您保存时,您一次读取 64 兆字节的文件(如果您真的很激进的话),然后将其流式传输到一个临时文件,直到您到达插入点。然后你流出 1 秒的片段,流式传输原始文件的其余部分,关闭临时写入文件,删除原始文件,并将新文件重命名为原始文件名。

当然,它比这更复杂一些。例如,在保存之前可能有多个编辑,以及一个撤消缓冲区。但我几乎可以向您保证,Audacity 在未保存的编辑复杂性方面受到可用 RAM 数量的限制。

于 2010-01-12T00:30:20.250 回答