Guarde y cargue MemoryStream en / desde un archivo

Estoy serializando una estructura en un MemoryStream y quiero guardar y cargar la estructura serializada.

Entonces, ¿cómo guardar un MemoryStream en un archivo y también cargarlo desde el archivo?

Puede usar los Stream.CopyTo MemoryStream.WriteTo o Stream.CopyTo (admitidos en framework version 4.5.2, 4.5.1, 4.5, 4) para escribir el contenido de la secuencia de la memoria en otra secuencia.

 memoryStream.WriteTo(fileStream); 

Actualizar:

 fileStream.CopyTo(memoryStream); memoryStream.CopyTo(fileStream); 

Suponiendo que el nombre de MemoryStream es ms .

Este código escribe MemoryStream en un archivo:

 using (FileStream file = new FileStream("file.bin", FileMode.Create, System.IO.FileAccess.Write)) { byte[] bytes = new byte[ms.Length]; ms.Read(bytes, 0, (int)ms.Length); file.Write(bytes, 0, bytes.Length); ms.Close(); } 

y esto lee un archivo en un MemoryStream:

 using (MemoryStream ms = new MemoryStream()) using (FileStream file = new FileStream("file.bin", FileMode.Open, FileAccess.Read)) { byte[] bytes = new byte[file.Length]; file.Read(bytes, 0, (int)file.Length); ms.Write(bytes, 0, (int)file.Length); } 

En .NET Framework 4+, simplemente puede copiar FileStream a MemoryStream y revertirlo de la manera siguiente:

 MemoryStream ms = new MemoryStream(); using (FileStream file = new FileStream("file.bin", FileMode.Open, FileAccess.Read)) file.CopyTo(ms); 

Y el reverso (MemoryStream a FileStream):

 using (FileStream file = new FileStream("file.bin", FileMode.Create, System.IO.FileAccess.Write)) ms.CopyTo(file); 

La transmisión realmente debería eliminarse, incluso si hay una excepción (muy probablemente en la E / S de archivos). Usar cláusulas es mi enfoque favorito para esto, así que para escribir tu MemoryStream, puedes usar:

 using (FileStream file = new FileStream("file.bin", FileMode.Create, FileAccess.Write)) { memoryStream.WriteTo(file); } 

Y por leerlo de nuevo:

 using (FileStream file = new FileStream("file.bin", FileMode.Open, FileAccess.Read)) { byte[] bytes = new byte[file.Length]; file.Read(bytes, 0, (int)file.Length); ms.Write(bytes, 0, (int)file.Length); } 

Si los archivos son grandes, vale la pena señalar que la operación de lectura utilizará el doble de memoria que el tamaño total del archivo . Una solución para eso es crear el MemoryStream desde la matriz de bytes; el siguiente código asume que no escribirá en esa secuencia.

 MemoryStream ms = new MemoryStream(bytes, writable: false); 

Mi investigación (a continuación) muestra que el búfer interno es el mismo conjunto de bytes a medida que lo pasa, por lo que debería ahorrar memoria.

 byte[] testData = new byte[] { 104, 105, 121, 97 }; var ms = new MemoryStream(testData, 0, 4, false, true); Assert.AreSame(testData, ms.GetBuffer()); 

Para cualquiera que busque las versiones cortas:

 var memoryStream = new MemoryStream(File.ReadAllBytes("1.dat")); File.WriteAllBytes("1.dat", memoryStream.ToArray()); 

La respuesta combinada para escribir en un archivo puede ser;

 MemoryStream ms = new MemoryStream(); FileStream file = new FileStream("file.bin", FileMode.Create, FileAccess.Write); ms.WriteTo(file); file.Close(); ms.Close(); 

Para cargar un archivo, me gusta mucho mejor

 MemoryStream ms = new MemoryStream(); using (FileStream fs = File.OpenRead(file)) { fs.CopyTo(ms); } 

Guardar en un archivo

 Car car = new Car(); car.Name = "Some fancy car"; MemoryStream stream = Serializer.SerializeToStream(car); System.IO.File.WriteAllBytes(fileName, stream.ToArray()); 

Cargar desde un archivo

 using (var stream = new MemoryStream(System.IO.File.ReadAllBytes(fileName))) { Car car = (Car)Serializer.DeserializeFromStream(stream); } 

dónde

 using System.IO; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; namespace Serialization { public class Serializer { public static MemoryStream SerializeToStream(object o) { MemoryStream stream = new MemoryStream(); IFormatter formatter = new BinaryFormatter(); formatter.Serialize(stream, o); return stream; } public static object DeserializeFromStream(MemoryStream stream) { IFormatter formatter = new BinaryFormatter(); stream.Seek(0, SeekOrigin.Begin); object o = formatter.Deserialize(stream); return o; } } } 

Originalmente, la implementación de esta clase se ha publicado aquí

y

 [Serializable] public class Car { public string Name; } 

Utilizo un Panel Control para agregar una imagen o incluso transmitir video, pero puede guardar la imagen en SQL Server como Image o MySQL como largeblob . Este código funciona para mí mucho. Echale un vistazo.

Aquí guardas la imagen

 MemoryStream ms = new MemoryStream(); Bitmap bmp = new Bitmap(panel1.Width, panel1.Height); panel1.DrawToBitmap(bmp, panel1.Bounds); bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); // here you can change the Image format byte[] Pic_arr = new byte[ms.Length]; ms.Position = 0; ms.Read(Pic_arr, 0, Pic_arr.Length); ms.Close(); 

Y aquí puedes cargar, pero utilicé un PictureBox Control.

 MemoryStream ms = new MemoryStream(picarr); ms.Seek(0, SeekOrigin.Begin); fotos.pictureBox1.Image = System.Drawing.Image.FromStream(ms); 

Hope ayuda.