Кэширование двоичного файла в C # - PullRequest
6 голосов
/ 29 мая 2009

Можно ли кэшировать двоичный файл в .NET и выполнять обычные файловые операции с кэшированным файлом?

Ответы [ 5 ]

13 голосов
/ 29 мая 2009

Способ сделать это - прочитать все содержимое из FileStream в объект MemoryStream, а затем использовать этот объект для ввода-вывода. Оба типа наследуются от Stream, поэтому использование будет фактически идентичным.

Вот пример:

private MemoryStream cachedStream;

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

Так что просто вызывайте метод CacheFile один раз, когда вы хотите кэшировать данный файл, а затем в любом другом месте кода используйте cachedStream для чтения. (Фактический файл будет закрыт, как только его содержимое будет кэшировано.) Единственное, что нужно помнить, это удалить cachedStream, когда вы закончите с ним.

4 голосов
/ 29 мая 2009

В любую современную ОС встроена система кэширования, поэтому фактически, когда вы взаимодействуете с файлом, вы взаимодействуете с кэшем в памяти файла.

Перед применением пользовательского кэширования необходимо задать важный вопрос: что происходит при изменении базового файла, поэтому моя кэшированная копия становится недействительной?

Вы можете усложнить ситуацию, если разрешено изменять кэшированную копию, и изменения необходимо сохранить обратно в базовый файл.

Если файл небольшой, проще использовать MemoryStream, как предлагается в другом ответе.

Если вам нужно сохранить изменения обратно в файл, вы можете написать класс-оболочку, который перенаправляет все в MemoryStream, но дополнительно имеет свойство IsDirty, которое устанавливает его в true при выполнении операции записи. Затем вы можете получить некоторый управляющий код, который активируется всякий раз, когда вы выбираете (в конце какой-то более крупной транзакции?), Проверяет (IsDirty == true) и сохраняет новую версию на диск. Это называется кэшированием с отложенной записью, поскольку изменения вносятся в память и фактически не сохраняются до некоторого времени позже.

Если вы действительно хотите усложнить задачу или у вас очень большой файл, вы можете реализовать свою собственную подкачку страниц, где вы выбираете размер буфера (возможно, 1 МБ?) И удерживаете небольшое количество byte[] страниц этого исправленный размер. На этот раз у вас будет грязный флаг для каждой страницы. Вы бы реализовали методы Stream, чтобы они скрывали детали от вызывающей стороны и при необходимости вставляли (или отбрасывали) буферы страниц.

Наконец, если вы хотите облегчить жизнь, попробуйте:

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

Он позволяет вам использовать тот же механизм SQL, что и SQL Server, но в файле, причем все происходит внутри вашего процесса, а не через внешний сервер RDBMS. Это, вероятно, даст вам гораздо более простой способ запрашивать и обновлять ваш файл и избежать необходимости большого количества рукописного постоянного кода.

3 голосов
/ 29 мая 2009

Ну, конечно, вы можете прочитать файл в массив 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 );
        }
}

Если вы беспокоитесь о производительности, то обычно достаточно встроенных механизмов различных методов доступа к файлам.

0 голосов
/ 29 мая 2009

В Lucene существует очень элегантная система кэширования, которая кэширует байты с диска в память и интеллектуально обновляет хранилище и т. Д. Возможно, вы захотите взглянуть на этот код, чтобы понять, как они сделай это. Возможно, вы также захотите ознакомиться со слоем хранения данных Microsoft SQL Server - поскольку команда MSSQL довольно скоро расскажет о некоторых наиболее важных деталях реализации.

0 голосов
/ 29 мая 2009

Я не знаю, что именно вы делаете, но я предлагаю следующее предложение (которое может или не может быть жизнеспособным в зависимости от того, что вы делаете):

Вместо того, чтобы только кэшировать содержимое файла, почему бы вам не поместить содержимое файла в хорошую строго типизированную коллекцию элементов, а затем кэшировать это? Это, вероятно, сделает поиск элементов немного проще и быстрее, так как в этом нет никакого анализа.

...