在 C# 中缓存二进制文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/925356/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 03:21:21  来源:igfitidea点击:

Caching a binary file in C#

c#filecachingfilestream

提问by

Is it possible to cache a binary file in .NET and do normal file operations on cached file?

是否可以在 .NET 中缓存二进制文件并对缓存文件进行正常的文件操作?

采纳答案by Noldorin

The way to do this is to read the entire contents from the FileStreaminto a MemoryStreamobject, and then use this object for I/O later on. Both types inherit from Stream, so the usage will be effectively identical.

这样做的方法是将 中的全部内容读FileStream入一个MemoryStream对象,然后使用该对象进行 I/O。两种类型都继承自Stream,因此用法实际上是相同的。

Here's an example:

下面是一个例子:

private MemoryStream cachedStream;

public void CacheFile(string fileName)
{
    cachedStream = new MemoryStream(File.ReadAllBytes(fileName));
}

So just call the CacheFilemethod once when you want to cache the given file, and then anywhere else in code use cachedStreamfor reading. (The actual file will been closed as soon as its contents was cached.) Only thing to remember is to dispose cachedStreamwhen you're finished with it.

因此CacheFile,当您想要缓存给定文件时,只需调用一次该方法,然后在代码中的任何其他地方cachedStream用于读取。(实际文件将在其内容被缓存后立即关闭。)唯一要记住的是cachedStream在完成后处理它。

回答by Daniel Earwicker

Any modern OS has a caching system built in, so in fact whenever you interact with a file, you are interacting with an in-memory cache of the file.

任何现代操作系统都内置了缓存系统,因此实际上,无论何时与文件交互,都在与文件的内存缓存交互。

Before applying custom caching, you need to ask an important question: what happens when the underlying file changes, so my cached copy becomes invalid?

在应用自定义缓存之前,你需要问一个重要的问题:当底层文件发生变化时会发生什么,所以我的缓存副本变得无效?

You can complicate matters further if the cached copy is allowed to change, and the changes need to be saved back to the underlying file.

如果允许更改缓存副本,并且需要将更改保存回基础文件,您可能会使问题进一步复杂化。

If the file is small, it's simpler just to use MemoryStreamas suggested in another answer.

如果文件很小,MemoryStream按照另一个答案中的建议使用会更简单。

If you need to save changes back to the file, you could write a wrapper class that forwards everything on to MemoryStream, but additionally has an IsDirty property that it sets to true whenever a write operation is performed. Then you can have some management code that kicks in whenever you choose (at the end of some larger transaction?), checks for (IsDirty == true)and saves the new version to disk. This is called "lazy write" caching, as the modifications are made in memory and are not actually saved until sometime later.

如果您需要将更改保存回文件,您可以编写一个包装类,将所有内容转发到MemoryStream,但另外还有一个 IsDirty 属性,每当执行写入操作时它都会设置为 true。然后你可以有一些管理代码,只要你选择(在一些更大的事务结束时?),检查(IsDirty == true)新版本并将其保存到磁盘。这称为“延迟写入”缓存,因为修改是在内存中进行的,并且直到某个时间后才实际保存。

If you really want to complicate matters, or you have a very large file, you could implement your own paging, where you pick a buffer size (maybe 1 MB?) and hold a small number of byte[]pages of that fixed size. This time you'd have a dirty flag for each page. You'd implement the Stream methods so they hide the details from the caller, and pull in (or discard) page buffers whenever necessary.

如果你真的想让事情复杂化,或者你有一个非常大的文件,你可以实现你自己的分页,在那里你选择一个缓冲区大小(可能是 1 MB?)并保存byte[]固定大小的少量页面。这次您将为每个页面设置一个脏标志。您将实现 Stream 方法,以便它们对调用者隐藏详细信息,并在必要时引入(或丢弃)页面缓冲区。

Finally, if you want an easier life, try:

最后,如果您想要更轻松的生活,请尝试:

http://www.microsoft.com/Sqlserver/2005/en/us/compact.aspx

http://www.microsoft.com/Sqlserver/2005/en/us/compact.aspx

It lets you use the same SQL engine as SQL Server but on a file, with everything happening inside your process instead of via an external RDBMS server. This will probably give you a much simpler way of querying and updating your file, and avoid the need for a lot of hand-written persistence code.

它允许您在文件上使用与 SQL Server 相同的 SQL 引擎,一切都在您的进程内发生,而不是通过外部 RDBMS 服务器。这可能会为您提供一种更简单的方式来查询和更新您的文件,并避免需要大量手写的持久性代码。

回答by tanascius

Well, you can of course read the file into a byte[] array and start working on it. And if you want to use a stream you can copy your FileStream into a MemoryStream and start working with it - like:

好吧,您当然可以将文件读入 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 );
        }
}

If you are concerned about performance - well, normally the build-in mechanisms of the different file access methods should be enough.

如果您关心性能 - 好吧,通常不同文件访问方法的内置机制应该足够了。

回答by Giovanni Galbo

I don't know what exactly you're doing, but I offer this suggestion (which may or may not be viable depending on what you're doing):

我不知道你到底在做什么,但我提供了这个建议(取决于你在做什么,这可能可行也可能不可行):

Instead of only caching the contents of the file, why don't you put the contents of the file in a nice strongly typed collection of items, and then cache that? It'll probably make searching for items a bit easier, and faster since there is no parsing involved.

为什么不只缓存文件的内容,为什么不把文件的内容放在一个很好的强类型项目集合中,然后缓存呢?由于不涉及解析,它可能会使搜索项目变得更容易、更快。

回答by Jonathan C Dickinson

There is a very elegant caching system in Lucenethat caches bytes from the disk into memory and intelligently updates the store etc. You might want to have a look at that code to get an idea of how they do it. You might also want to read up on the Microsoft SQL Server data storage layer - as the MSSQL team is pretty forthcoming about some of the more crucial implementation details.

Lucene中有一个非常优雅的缓存系统,它将字节从磁盘缓存到内存中,并智能地更新存储等。您可能想查看该代码以了解它们是如何做到的。您可能还想阅读 Microsoft SQL Server 数据存储层 - 因为 MSSQL 团队非常愿意介绍一些更重要的实现细节。