4

想象一个通过组合和/或编辑其他文件来创建大文件的应用程序。例如,一个应用程序:

  • 打开图像档案
  • 添加或替换一些图像
  • 更改现有图像的一部分
  • 使用生成的图像集创建新存档

可以按任何顺序添加/替换/更改图像,因此在执行结束之前无法创建新存档。

天真的方法是为MemoryStream原始存档中的每个图像创建一组对象,然后在需要时更改/删除/替换流,然后将该组写入新存档。这种方法可能会在执行速度方面给出最好的结果。

问题很明显:并不总是有足够的内存来保存一组流。

在这种情况下你会推荐什么?

我想我应该用一些速度换取内存,并使用某种临时的非内存存储。不过,我不确定要使用什么。

我应该使用内存映射文件吗?还是带有某种创建和删除机制的普通旧临时文件?也许还有别的?

4

4 回答 4

2

您可以FileStream像使用MemoryStream. 它本质上将确定缓冲的负担以及所有这些都放在了操作系统上。操作系统确实最了解,并让驱动程序和硬件处理复杂的缓存和微调。只需编写易于理解和配置文件的代码,配置文件,配置文件。

如果分析显示需要,您可能可以混合这两种类型的流以获得性能良好且看起来不错的东西。

于 2012-04-20T12:14:07.320 回答
2

首先,请注意.net 对 LOH 的限制,基本上对于 LOH 对象,内存不会进行碎片整理,因此如果您连续创建和处理大量大对象,您“很可能”会得到“内存不足异常”因为碎片化的内存孔可能无法给您足够大的连续内存空间(.net 4.5 及更高版本已对此进行了一定程度的优化,但问题仍然存在)。因此,要回答您的问题,很大程度上取决于您的机器的体系结构,如果它是具有大量 RAM 的 64 位,并且您知道您的文件将恰好适合 LOH 问题,请使用内存中的对象,否则为迈克尔建议使用文件流颠簸必然会发生。

于 2012-04-20T13:01:13.667 回答
2

一种方法是使用文件和文件系统——大部分是——并提供某种内存缓存或映射。

如果您正在处理大量或相当大的文件-那么您无法真正将其与内存大小相匹配(或解压缩内存中的完整存档)-除非我们谈论的是额外的硬件、RAM。

具体来说,我个人会选择......

class MemoryArchive {}  

...它冒充文件的前端,在后端存档。

您解压缩磁盘上的存档文件,临时文件夹 - 与大多数解压缩工具一样,然后处理“较小单元”的访问,即文件。

MemoryArchive的行为基本上就像所有都在内存中,所以你需要有一些映射来代替内存流(或者你决定用于直接访问对象级别的任何东西)到磁盘上的临时文件,文件流。

并且可能是一些处理同步的强大方法 - 和/或错误,问题 - 因为您需要确保内存中的内容与磁盘上的内容同步 - 并保持“集成”完好无损。

那时(并且取决于系统的性质等),主要任务可能是编写某种事务 - 围绕文件系统存储 - 这是您开始类似于数据库管理系统的地方。但那将是“规模的另一端”——如果你可以没有它生活,并保持简单,它可能不会有那么大的问题。

只是一个想法,尽管这完全取决于您的具体细节 -
即事物的规模(可能会有很大差异 - 即如果内存允许在某些情况下您可以加载,并且处理速度足够快),“小变化”如何' 档案内与档案的大小、更改的频率和性质。

在最简单的情况下,我几乎会将内容存储为临时文件并根据需要处理较小的增量更改。

并且拥有某种方式MemoryArchive会给你未来的事情提供一个围栏 - 所以你可以改变它,或者根据档案的大小等混合几种方法。实际上,在这些情况下,一些“混合方法”通常是最好的,因为在处理不同的文件、大小时,您几乎无法做出“一刀切”的解决方案。

希望这可以帮助,

于 2012-04-20T12:56:26.873 回答
1

我应该使用内存映射文件吗?

这肯定是首先想到的。这种方法的唯一问题是文件大小是否最终会占用所有映射空间。

于 2012-04-20T12:14:37.127 回答