Speichern und laden Sie MemoryStream in / aus einer Datei


281

Ich serialisiere eine Struktur in eine MemoryStream und möchte die serialisierte Struktur speichern und laden.

Also, wie man ein MemoryStreamin eine Datei speichert und es auch wieder aus der Datei lädt?


Wenn Sie in einer Datei speichern müssen, warum verwenden Sie eine MemoryStream?
Oded

@Oded Was soll ich verwenden? Kannst du mir ein Beispiel geben?
Mahdi Ghiasi

Antworten:


365

Sie können MemoryStream.WriteTooder Stream.CopyTo(in Framework-Version 4.5.2, 4.5.1, 4.5, 4 unterstützt) Methoden verwenden, um Inhalte des Speicherstroms in einen anderen Stream zu schreiben.

memoryStream.WriteTo(fileStream);

Aktualisieren:

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

13
memoryStream.CopyTo schien bei mir nicht zu funktionieren, während WriteTo es tat. Ich denke, vielleicht lag es daran, dass mein memoryStream.Position nicht 0 war
Mark Adamson

10
Ja, das ist richtig. Der Unterschied zwischen ihnen besteht darin, dass CopyTo von jeder aktuellen Position kopiert wird, anstatt immer von Anfang an wie WriteTo.
AnorZaken

6
Hinzufügen [file|memory]Stream.Seek(0, SeekOrigin.Begin);bevor CopyTodie aktuelle Position auf 0 gesetzt, so dass CopyToder kompletten Strom kopieren.
Martin Backasch

263

Angenommen, der Name MemoryStream lautet ms .

Dieser Code schreibt MemoryStream in eine Datei:

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

und dies liest eine Datei in einen 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);
}

In .Net Framework 4+ können Sie FileStream einfach in MemoryStream kopieren und so einfach umkehren:

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

Und die Umkehrung (MemoryStream zu FileStream):

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

1
Kann ich fragen, warum Sie FileMode.Create im Lesebeispiel gegen FileMode.Open verwenden?
Philter

6
Anstatt den Speicherstrom manuell in ein Array zu kopieren, können Sie im ersten Codeblock die integrierte ms.ToArray()Funktion verwenden.
Gman

5
Es ist wichtig, ms.Position = 0 zu setzen, da sonst das Byte-Array (und die Datei) alle Nullen enthalten.
Gregory Khrapunovich

1
@ Fernando68 das Konstrukt using (...){ }hat genau den gleichen Effekt.
Fabricio Araujo

2
Nur als Warnung an andere, die (FileStream 'und' ms.CopyTo (file) 'verwenden, wird die Position am Ende der Datei festgelegt, und Sie müssen den Memorystream anschließend zurücksetzen
Rebecca,

63

Der Stream sollte wirklich entsorgt werden, auch wenn es eine Ausnahme gibt (sehr wahrscheinlich bei Datei-E / A). Die Verwendung von Klauseln ist mein bevorzugter Ansatz, sodass Sie zum Schreiben Ihres MemoryStream Folgendes verwenden können:

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

Und zum Zurücklesen:

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

Wenn die Dateien groß sind, ist zu beachten, dass der Lesevorgang doppelt so viel Speicher benötigt wie die gesamte Dateigröße . Eine Lösung hierfür besteht darin, den MemoryStream aus dem Byte-Array zu erstellen. Im folgenden Code wird davon ausgegangen, dass Sie dann nicht in diesen Stream schreiben.

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

Meine Forschung (unten) zeigt, dass der interne Puffer das gleiche Byte-Array ist, mit dem Sie ihn übergeben, sodass Speicherplatz gespart werden sollte.

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

41

Für alle, die nach Kurzversionen suchen:

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

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

20

Die kombinierte Antwort zum Schreiben in eine Datei kann sein;

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

15

In einer Datei speichern

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

Laden aus einer Datei

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

wo

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

Ursprünglich wurde die Implementierung dieser Klasse hier veröffentlicht

und

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

14

Zum Laden einer Datei gefällt mir das viel besser

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

Wenn eine Datei in Microsoft Word geöffnet wird - gibt es eine Möglichkeit, aus dieser Datei einen Speicherstrom zu erstellen? Ich
erhalte die

@FrenkyB Ich stoße auch oft darauf. Wenn Sie die Datei in Word oder einer anderen App geöffnet haben, können Sie dies nicht tun. Schließen Sie einfach die Datei in Word.
Kristopher

@FrenkyB Kannst du eine File.Copy machen? Ich habe festgestellt, dass das funktioniert, dann aus dieser Datei in einen Stream gelesen und die neue Datei gelöscht ... schrecklich, scheint aber zu funktionieren.
Ridecar2

3

Ich verwende ein Bedienfeld, um ein Bild hinzuzufügen oder sogar Videos zu streamen, aber Sie können das Bild auf SQL Server als Image oder MySQL als Largeblob speichern . Dieser Code funktioniert bei mir sehr. Hör zu.

Hier speichern Sie das Bild

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

Und hier können Sie laden, aber ich habe ein PictureBox-Steuerelement verwendet.

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

Hoffnung hilft.


1
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Text;

namespace ImageWriterUtil
{
    public class ImageWaterMarkBuilder
    {
        //private ImageWaterMarkBuilder()
        //{
        //}
        Stream imageStream;
        string watermarkText = "©8Bytes.Technology";
        Font font = new System.Drawing.Font("Brush Script MT", 30, FontStyle.Bold, GraphicsUnit.Pixel);
        Brush brush = new SolidBrush(Color.Black);
        Point position;
        public ImageWaterMarkBuilder AddStream(Stream imageStream)
        {
            this.imageStream = imageStream;
            return this;
        }
        public ImageWaterMarkBuilder AddWaterMark(string watermarkText)
        {
            this.watermarkText = watermarkText;
            return this;
        }
        public ImageWaterMarkBuilder AddFont(Font font)
        {
            this.font = font;
            return this;
        }

        public ImageWaterMarkBuilder AddFontColour(Color color)
        {
            this.brush = new SolidBrush(color);
            return this;
        }
        public ImageWaterMarkBuilder AddPosition(Point position)
        {
            this.position = position;
            return this;
        }

        public void CompileAndSave(string filePath)
        {

            //Read the File into a Bitmap.
            using (Bitmap bmp = new Bitmap(this.imageStream, false))
            {
                using (Graphics grp = Graphics.FromImage(bmp))
                {


                    //Determine the size of the Watermark text.
                    SizeF textSize = new SizeF();
                    textSize = grp.MeasureString(watermarkText, font);

                    //Position the text and draw it on the image.
                    if (position == null)
                        position = new Point((bmp.Width - ((int)textSize.Width + 10)), (bmp.Height - ((int)textSize.Height + 10)));
                    grp.DrawString(watermarkText, font, brush, position);

                    using (MemoryStream memoryStream = new MemoryStream())
                    {
                        //Save the Watermarked image to the MemoryStream.
                        bmp.Save(memoryStream, ImageFormat.Png);
                        memoryStream.Position = 0;
                       // string fileName = Path.GetFileNameWithoutExtension(filePath);
                        // outPuthFilePath = Path.Combine(Path.GetDirectoryName(filePath), fileName + "_outputh.png");
                        using (FileStream file = new FileStream(filePath, FileMode.Create, System.IO.FileAccess.Write))
                        {
                            byte[] bytes = new byte[memoryStream.Length];
                            memoryStream.Read(bytes, 0, (int)memoryStream.Length);
                            file.Write(bytes, 0, bytes.Length);
                            memoryStream.Close();
                        }
                    }
                }
            }

        }
    }
}

Verwendung :-

ImageWaterMarkBuilder.AddStream(stream).AddWaterMark("").CompileAndSave(filePath);
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.