La manera más rápida es serializar manualmente los datos.
Una manera fácil de hacerlo es creando un FileStream, y luego envolverlo en un BinaryWriter/BinaryReader.
Usted tiene acceso a las funciones de escribir las estructuras de datos básicos (numbers
, string
, char
, byte[]
y char[]
).
Una manera fácil de escribir un int[]
(innecesario si es de tamaño fijo) es anteponiendo la longitud de la matriz con un int/largo (dependiendo del tamaño, sin signo no ofrece ninguna ventaja, ya que las matrices usan tipos de datos firmados para su almacenamiento de longitud). Y luego escribe todos los enteros.
Dos maneras de escribir todas las entradas sería:
1. Simplemente recorra toda la matriz.
2. Convertir en un byte[]
y escribir usando BinaryWriter.Write(byte[])
Estos es cómo se puede aplicar a los dos:
// Writing
BinaryWriter writer = new BinaryWriter(new FileStream(...));
int[] intArr = new int[1000];
writer.Write(intArr.Length);
for (int i = 0; i < intArr.Length; i++)
writer.Write(intArr[i]);
// Reading
BinaryReader reader = new BinaryReader(new FileStream(...));
int[] intArr = new int[reader.ReadInt32()];
for (int i = 0; i < intArr.Length; i++)
intArr[i] = reader.ReadInt32();
// Writing, method 2
BinaryWriter writer = new BinaryWriter(new FileStream(...));
int[] intArr = new int[1000];
byte[] byteArr = new byte[intArr.Length * sizeof(int)];
Buffer.BlockCopy(intArr, 0, byteArr, 0, intArr.Length * sizeof(int));
writer.Write(intArr.Length);
writer.Write(byteArr);
// Reading, method 2
BinaryReader reader = new BinaryReader(new FileStream(...));
int[] intArr = new int[reader.ReadInt32()];
byte[] byteArr = reader.ReadBytes(intArr.Length * sizeof(int));
Buffer.BlockCopy(byteArr, 0, intArr, 0, byteArr.Length);
decidí poner todo esto a la prueba, con una serie de números enteros 10000 Ejecuté la prueba 10000 veces.
Resultó que el método uno consume un promedio de 888200ns en mi sistema (aproximadamente 0.89ms).
Mientras que el método 2 solo consume un promedio de 568600ns en mi sistema (0.57ms en promedio).
Ambos tiempos incluyen el trabajo que el recolector de basura tiene que hacer.
Obviamente, el método 2 es más rápido que el método 1, aunque posiblemente menos legible.
Otra razón por la cual el método 1 puede ser mejor que el método 2 se debe a que el método 2 requiere el doble de la cantidad de memoria RAM libre que los datos que vas a escribir (el original int[]
y la byte[]
que se convierte de la int[]
), cuando se trata de con RAM limitada/archivos extremadamente grandes (hablando de 512MB +), aunque si este es el caso, siempre puede hacer una solución híbrida, por ejemplo, grabando 128 MB a la vez.
Tenga en cuenta que el método 1 también requiere este espacio adicional, pero debido a que está dividido en 1 operación por elemento del int[]
, puede liberar la memoria mucho antes.
Algo como esto, escribirá 128MB de una int[]
a la vez:
const int WRITECOUNT = 32 * 1024 * 1024; // 32 * sizeof(int)MB
int[] intArr = new int[140 * 1024 * 1024]; // 140 * sizeof(int)MB
for (int i = 0; i < intArr.Length; i++)
intArr[i] = i;
byte[] byteArr = new byte[WRITECOUNT * sizeof(int)]; // 128MB
int dataDone = 0;
using (Stream fileStream = new FileStream("data.dat", FileMode.Create))
using (BinaryWriter writer = new BinaryWriter(fileStream))
{
while (dataDone < intArr.Length)
{
int dataToWrite = intArr.Length - dataDone;
if (dataToWrite > WRITECOUNT) dataToWrite = WRITECOUNT;
Buffer.BlockCopy(intArr, dataDone, byteArr, 0, dataToWrite * sizeof(int));
writer.Write(byteArr);
dataDone += dataToWrite;
}
}
Tenga en cuenta que esto es sólo para la escritura, la lectura de las obras de manera diferente también: P. Espero que esto te brinde más información al tratar con archivos de datos muy grandes :).
No está muy claro para mí lo que está pidiendo, ¿podría mostrarnos su código actual y luego podemos tratar de encontrar la manera de mejorarlo? –
¿Cómo se almacenan los datos exactamente? Una línea por conjunto? – VMAtm
@JonSkeet ¿Está más claro ahora? – Sven