Save and load MemoryStream to/from a file

718,552

Solution 1

You may use MemoryStream.WriteTo or Stream.CopyTo (supported in framework version 4.5.2, 4.5.1, 4.5, 4) methods to write content of memory stream to another stream.

memoryStream.WriteTo(fileStream);

Update:

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

Solution 2

Assuming that MemoryStream name is ms.

This code writes down MemoryStream to a file:

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

and this reads a file to a 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+, You can simply copy FileStream to MemoryStream and reverse as simple as this:

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

And the Reverse (MemoryStream to FileStream):

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

Solution 3

The stream should really by disposed of even if there's an exception (quite likely on file I/O) - using clauses are my favourite approach for this, so for writing your MemoryStream, you can use:

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

And for reading it back:

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

If the files are large, then it's worth noting that the reading operation will use twice as much memory as the total file size. One solution to that is to create the MemoryStream from the byte array - the following code assumes you won't then write to that stream.

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

My research (below) shows that the internal buffer is the same byte array as you pass it, so it should save memory.

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

Solution 4

For anyone looking for the short versions:

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

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

Solution 5

The combined answer for writing to a file can be;

MemoryStream ms = new MemoryStream();    
FileStream file = new FileStream("file.bin", FileMode.Create, FileAccess.Write);
ms.WriteTo(file);
file.Close();
ms.Close();
Share:
718,552
Mahdi Ghiasi
Author by

Mahdi Ghiasi

Updated on July 08, 2022

Comments

  • Mahdi Ghiasi
    Mahdi Ghiasi almost 2 years

    I am serializing an structure into a MemoryStream and I want to save and load the serialized structure.

    So, How to Save a MemoryStream into a file and also load it back from file?

  • Philter
    Philter about 11 years
    Can I ask why you use FileMode.Create in the read sample vs FileMode.Open?
  • Gman
    Gman about 11 years
    In the first code block, instead of manually copying memory stream to array, you can use built-in ms.ToArray() function.
  • Gregory Khrapunovich
    Gregory Khrapunovich over 10 years
    It's important to set ms.Position = 0, otherwise byte array (and file) will contain all zeros.
  • FrenkyB
    FrenkyB over 10 years
    If file is opened in Microsoft Word - is there a way for creating a memory stream from that file? I am receiving an error 'file is opened by another process'
  • Mark Adamson
    Mark Adamson almost 10 years
    memoryStream.CopyTo didn't seem to work for me, while WriteTo did. I think perhaps it was because my memoryStream.Position wasn't 0
  • AnorZaken
    AnorZaken over 8 years
    Yes that is correct. The difference between them is that CopyTo copies from whatever the current position is instead of always from the begining like WriteTo does.
  • Kristopher
    Kristopher over 8 years
    @FrenkyB I also run into this a lot. If you have the file open in Word or some other app then you can't get do it. Just close the file in Word.
  • Fabricio Araujo
    Fabricio Araujo about 7 years
    @Fernando68 the construct using (...){ } has the exactly the same effect.
  • Martin Backasch
    Martin Backasch over 6 years
    Adding [file|memory]Stream.Seek(0, SeekOrigin.Begin); before CopyTo will set the current position to 0, so that CopyTo will copy the complete stream.
  • Rebecca
    Rebecca over 5 years
    Just as a warning to others 'using (FileStream' and 'ms.CopyTo(file)' sets the position tothe end of the file and you need to reset the memorystream afterwards.
  • ridecar2
    ridecar2 almost 5 years
    @FrenkyB Can you do a File.Copy? I have found that to work, then read from that file into a stream and delete the new file... horrible, but seems to work.
  • Paras Parmar
    Paras Parmar over 3 years
    @GregoryKhrapunovich , Its like a cassete tape, while we create it... we write to the very end. Now the tape has to be rewound before we put it in the walkman.
  • Darpan Gupta
    Darpan Gupta almost 3 years
    Thanks.You made it so simple and in 2 lines only.
  • CorrM
    CorrM about 2 years
    Keep in mind this will re-allocate the whole buffer (MemoryStream.ToArray) byte[] copy = GC.AllocateUninitializedArray<byte>(count);