2009-05-29 36 views
5

¿Es posible almacenar en caché un archivo binario en .NET y realizar operaciones normales de archivos en el archivo en caché?Almacenamiento en memoria caché de un archivo binario en C#

+2

¿Huh? ¿A qué te refieres con 1) caché? 2) Archivo binario (por ejemplo, archivo de texto, ejecutable, imagen)? 3) operaciones de "archivo normal"? –

+1

¿Por qué también quieres guardarlo en caché? Tal vez es innecesario? – uriDium

+0

use el caso de uso por favor. –

Respuesta

11

La manera de hacerlo es leer todo el contenido del FileStream en un objeto MemoryStream y luego usar este objeto para E/S más adelante. Ambos tipos heredan de Stream, por lo que el uso será efectivamente idéntico.

He aquí un ejemplo:

private MemoryStream cachedStream; 

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

Así que llama al método CacheFile vez cuando se desea almacenar en caché el archivo dado, y luego cualquier otro lugar en el uso de código cachedStream para la lectura. (El archivo real se cerrará tan pronto como se haya almacenado en caché su contenido). Lo único que debe recordar es deshacerse del cachedStream cuando haya terminado de usarlo.

+3

+1: Creo que esto podría ser lo que quiere el asker. –

+0

Probablemente esté bien; el único problema sería si hablamos de un archivo que tiene un tamaño de GB o dos. –

+2

Sí, este método, por supuesto, deja de ser útil cuando el tamaño del archivo se aproxima al de la memoria RAM. En ese punto, sin embargo, debe utilizar un servidor de base de datos, así que supongo que esto no será un problema aquí. – Noldorin

3

Cualquier sistema operativo moderno tiene incorporado un sistema de almacenamiento en caché, de modo que cada vez que interactúa con un archivo, está interactuando con un caché en memoria del archivo.

Antes de aplicar el almacenamiento en caché personalizado, debe hacer una pregunta importante: ¿qué sucede cuando el archivo subyacente cambia, por lo que mi copia en caché no es válida?

Puede complicar aún más las cosas si se permite que la copia en caché cambie, y los cambios deben guardarse nuevamente en el archivo subyacente.

Si el archivo es pequeño, es más simple usar MemoryStream como se sugiere en otra respuesta.

Si necesita guardar los cambios en el archivo, puede escribir una clase contenedora que reenvía todo a MemoryStream, pero adicionalmente tiene una propiedad IsDirty que establece en verdadero cada vez que se realiza una operación de escritura. Entonces puede tener algún código de administración que se active cada vez que elija (al final de una transacción más grande?), Comprueba el (IsDirty == true) y guarda la nueva versión en el disco. Esto se denomina almacenamiento en caché "escritura diferida", ya que las modificaciones se realizan en la memoria y no se guardan hasta un tiempo después.

Si realmente quiere complicar las cosas, o si tiene un archivo muy grande, podría implementar su propia búsqueda, donde elija un tamaño de búfer (¿quizás 1 MB?) Y mantenga un pequeño número de byte[] páginas tamaño. Esta vez tendrías una bandera sucia para cada página. Implementará los métodos Stream para que oculten los detalles de la persona que llama, y ​​extraiga (o descarte) los búferes de la página siempre que sea necesario.

Por último, si desea una vida más fácil, tratar:

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

Se le permite utilizar el mismo motor SQL como SQL Server, pero en un fichero, con todo lo que ocurre dentro de su proceso en lugar de a través de una servidor RDBMS externo. Esto probablemente le dará una forma mucho más simple de consultar y actualizar su archivo, y evitará la necesidad de una gran cantidad de código de persistencia escrito a mano.

+0

¿No es eso lo que es un archivo mapeado en memoria (http://en.wikipedia.org/wiki/Memory- mapped_file)? Aun así, creo que el OP quiere cerrar el archivo manejador lo antes posible. – Noldorin

+0

Mapeo de memoria un archivo es donde el sistema operativo usa un archivo (de su elección) para proporcionar el almacén de respaldo de memoria virtual para una región del espacio de direcciones del proceso. (El archivo de página cumple esta función para la memoria de asignación normal). Me refiero al hecho de que el sistema operativo tiene un caché de disco que funciona independientemente de cómo acceda al archivo. Pruebe usar grep o similar para buscar unos cientos de MB de archivos de texto. La segunda vez que lo haga, sucederá mucho más rápido y su disco duro no emitirá ningún sonido, porque está todo en la memoria. –

+0

@Earwicker: Sí, estoy seguro de que tienes razón. Sin embargo, copiar el contenido en un MemoryStream parece ser la mejor solución porque a) no mantiene un bloqueo en el archivo b) Sospecho que ofrecerá mejoras en el rendimiento. – Noldorin

3

Bueno, por supuesto puede leer el archivo en una matriz de bytes [] y comenzar a trabajar en él. Y si desea utilizar una corriente podrá copiar sus FileStream en una MemoryStream y empezar a trabajar con él - como:

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); 
     } 
} 

Si usted está preocupado por el rendimiento - así, normalmente los mecanismos construir-en de los diferentes archivos los métodos de acceso deberían ser suficientes.

0

No sé qué es exactamente lo que está haciendo, pero me ofrezco esta sugerencia (que puede o no ser viables en función de lo que está haciendo):

En lugar de sólo el almacenamiento en caché el contenido de la archivo, ¿por qué no pones el contenido del archivo en una bonita colección fuertemente tipada de elementos y luego lo almacenas en caché? Probablemente hará que la búsqueda de elementos sea un poco más fácil, y más rápido ya que no hay análisis involucrados.

+0

archivo contiene una gran cantidad de registros. en realidad es el archivo binario de la base de datos del país maxmind –

+0

, ¿podemos suponer que el verdadero problema es que no obtiene el rendimiento que desea de sus consultas? –

0

Hay un sistema de caché muy elegante en Lucene que almacena en caché los bytes del disco en la memoria y actualiza inteligentemente la tienda, etc. Es posible que desee echar un vistazo a ese código para tener una idea de cómo lo hacen. También es posible que desee leer en la capa de almacenamiento de datos de Microsoft SQL Server, ya que el equipo de MSSQL es bastante cercano acerca de algunos de los detalles de implementación más cruciales.

Cuestiones relacionadas