是否可以在 .NET 中缓存二进制文件并对缓存文件执行正常文件操作?
5 回答
这样做的方法是将整个内容从 中读取FileStream
到一个MemoryStream
对象中,然后使用该对象进行 I/O。两种类型都继承自Stream
,因此用法实际上是相同的。
这是一个例子:
private MemoryStream cachedStream;
public void CacheFile(string fileName)
{
cachedStream = new MemoryStream(File.ReadAllBytes(fileName));
}
CacheFile
因此,当您想要缓存给定文件时,只需调用该方法一次,然后在代码中的其他任何地方cachedStream
用于读取。(实际文件将在其内容被缓存后立即关闭。)唯一要记住的是cachedStream
在您完成后处理它。
任何现代操作系统都内置了缓存系统,因此实际上,无论何时与文件交互,您都是在与文件的内存缓存进行交互。
在应用自定义缓存之前,您需要问一个重要的问题:当底层文件更改时会发生什么,所以我的缓存副本变得无效?
如果允许更改缓存的副本,并且需要将更改保存回基础文件,您可能会使事情变得更加复杂。
如果文件很小,那么MemoryStream
按照另一个答案中的建议使用会更简单。
如果您需要将更改保存回文件,您可以编写一个将所有内容转发到的包装器类MemoryStream
,但另外还有一个 IsDirty 属性,每当执行写入操作时它设置为 true。然后你可以有一些管理代码在你选择时启动(在一些更大的事务结束时?),检查(IsDirty == true)
新版本并将其保存到磁盘。这称为“延迟写入”缓存,因为修改是在内存中进行的,并且直到稍后的某个时间才会真正保存。
如果您真的想使事情复杂化,或者您有一个非常大的文件,您可以实现自己的分页,您可以在其中选择一个缓冲区大小(可能是 1 MB?)并保存少量byte[]
固定大小的页面。这一次,每个页面都有一个脏标志。您将实现 Stream 方法,以便它们向调用者隐藏详细信息,并在必要时拉入(或丢弃)页面缓冲区。
最后,如果您想要更轻松的生活,请尝试:
http://www.microsoft.com/Sqlserver/2005/en/us/compact.aspx
它允许您使用与 SQL Server 相同的 SQL 引擎,但在文件上,一切都发生在您的进程内,而不是通过外部 RDBMS 服务器。这可能会为您提供一种更简单的查询和更新文件的方法,并避免需要大量手写的持久性代码。
好吧,您当然可以将文件读入 byte[] 数组并开始处理它。如果您想使用流,您可以将 FileStream 复制到 MemoryStream 并开始使用它 - 例如:
public static void CopyStream( Stream input, Stream output )
{
var buffer = new byte[32768];
int readBytes;
while( ( readBytes = input.Read( buffer, 0, buffer.Length ) ) > 0 )
{
output.Write( buffer, 0, readBytes );
}
}
如果您关心性能 - 好吧,通常不同文件访问方法的内置机制就足够了。
我不知道你到底在做什么,但我提供了这个建议(根据你在做什么,这可能可行也可能不可行):
与其只缓存文件的内容,为什么不把文件的内容放在一个很好的强类型项目集合中,然后缓存呢?由于不涉及解析,它可能会使搜索项目更容易、更快。
Lucene中有一个非常优雅的缓存系统,它可以将磁盘中的字节缓存到内存中并智能地更新存储等。您可能想查看该代码以了解它们是如何做到的。您可能还想阅读 Microsoft SQL Server 数据存储层 - 因为 MSSQL 团队非常愿意了解一些更重要的实现细节。