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?
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);
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);
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());
Pour ceux qui recherchent les versions courtes:
var memoryStream = new MemoryStream(File.ReadAllBytes("1.dat"));
File.WriteAllBytes("1.dat", memoryStream.ToArray());
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();
Pour charger un fichier, j'aime beaucoup mieux ça
MemoryStream ms = new MemoryStream();
using (FileStream fs = File.OpenRead(file))
{
fs.CopyTo(ms);
}
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);
}
où
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;
}
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.