web-dev-qa-db-fra.com

Enregistrer et charger MemoryStream dans / à partir d'un fichier

Je suis en train de sérialiser une structure dans un MemoryStream et je veux enregistrer et charger la structure sérialisée.

Alors, comment enregistrer un MemoryStream dans un fichier et le charger à partir d'un fichier?

252
Mahdi Ghiasi

Vous pouvez utiliser les méthodes MemoryStream.WriteTo ou Stream.CopyTo (prises en charge dans les versions de framework 4.5.2, 4.5.1, 4.5, 4) pour écrire le contenu du flux de mémoire dans un autre flux.

memoryStream.WriteTo(fileStream);

Mise à jour:

fileStream.CopyTo(memoryStream);
memoryStream.CopyTo(fileStream);
331
adatapost

En supposant que le nom MemoryStream soit ms.

Ce code écrit MemoryStream dans un fichier:

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

et cela lit un fichier sur 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);
}

Dans .Net Framework 4+, vous pouvez simplement copier FileStream vers MemoryStream et inverser aussi simple que cela:

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

Et l'inverse (MemoryStream à FileStream):

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

Le flux devrait vraiment être éliminé même s'il y a une exception (probablement sur les entrées/sorties de fichiers) - les clauses d'utilisation sont mon approche préférée pour cela, donc pour écrire votre MemoryStream, vous pouvez utiliser:

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

Et pour le relire:

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 les fichiers sont volumineux, il est intéressant de noter que l'opération de lecture utilisera deux fois plus de mémoire que la taille totale du fichier. Une solution à cela consiste à créer le MemoryStream à partir du tableau d'octets - le code suivant suppose que vous n'écrirez pas dans ce flux.

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

Ma recherche (ci-dessous) montre que le tampon interne est le même tableau d'octets que vous le transmettez, il devrait donc économiser de la mémoire.

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

Pour ceux qui recherchent les versions courtes:

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

File.WriteAllBytes("1.dat", memoryStream.ToArray()); 
36
Slai

La réponse combinée pour écrire dans un fichier peut être:

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

Pour charger un fichier, j'aime beaucoup mieux ça

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

Sauvegarder dans un fichier

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

Charger depuis un fichier

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

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

À l'origine, l'implémentation de cette classe a été publiée ici

et

[Serializable]
public class Car
{
    public string Name;
}
13
Vadim Gremyachev

J'utilise un panneau de contrôle pour ajouter une image ou même une vidéo en continu, mais vous pouvez enregistrer l'image sur SQL Server sous le nom Image ou MySQL sous le format largeblob. Ce code fonctionne beaucoup pour moi. Vérifiez-le.

Ici vous enregistrez l'image

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

Et ici, vous pouvez charger, mais j'ai utilisé un contrôle PictureBox.

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

L'espoir aide.

3
Leinad