2011-12-24 2 views
182

Я сериализую структуру в MemoryStream, и я хочу сохранить и загрузить сериализованную структуру.Сохранение и загрузка MemoryStream в/из файла

Итак, как сохранить MemoryStream в файл, а также загрузить его из файла?

+0

Если вам нужно сохранить в файл, почему вы с помощью 'MemoryStream'? – Oded

+0

@Oded Что следует использовать? Можете ли вы привести мне пример? –

ответ

269

Вы можете использовать MemoryStream.WriteTo или Stream.CopyTo (поддерживаемые в версии 4.5.2, 4.5.1, 4.5, 4) способы записи содержимого потока памяти в другой поток.

memoryStream.WriteTo(fileStream); 

Update:

fileStream.CopyTo(memoryStream); 
memoryStream.CopyTo(fileStream); 
+8

memoryStream.CopyTo, похоже, не работает для меня, а WriteTo. Я думаю, возможно, это потому, что мой memoryStream.Position не был 0 –

+6

Да, это правильно. Разница между ними заключается в том, что CopyTo копирует с любой текущей позиции, а не всегда с самого начала, как это делает WriteTo. – AnorZaken

+0

Добавление ['[file | memory] Stream.Seek (0, SeekOrigin.Begin);'] (https://msdn.microsoft.com/en-us/library/system.io.stream.seek (v = vs .110) .aspx) до того, как 'CopyTo' установит текущую позицию в 0, так что' CopyTo' скопирует полный поток. –

184

Предполагая, что имя MemoryStream является ms.

Этот код записывает MemoryStream в файл:

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

и это читает файл в 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); 
} 

В .Net Framework 4 +, Вы можете просто скопировать FileStream в MemoryStream и наоборот:

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

И обратный (MemoryStream to FileStream):

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

Могу ли я спросить, почему вы используете FileMode.Create в read sample vs FileMode.Open? – Philter

+4

В первом блоке кода вместо ручного копирования потока памяти в массив вы можете использовать встроенную функцию 'ms.ToArray()'. – Gman

+4

Важно установить ms.Position = 0, в противном случае массив байтов (и файл) будет содержать все нули. –

17

Комбинированный ответ для записи в файл может быть;

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

поток должен действительно по УТИЛИЗИРОВАТЬ даже если есть исключение (вполне вероятно, в файле I/O) - используя пункты мой любимый подход к этому, поэтому для написания MemoryStream, вы можете использовать:

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

И для ее обратно:

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

Если файлы велики, то стоит отметить, что операция чтения будет использовать в два раза больше памяти, т он общий размер файла. Одним из решений этого является создание MemoryStream из массива байтов - следующий код предполагает, что вы не будете писать в этот поток.

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

Мои исследования (ниже) показывает, что внутренний буфер является тот же массив байт, как вы передаете его, поэтому он должен сохранить память.

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

лучший ответ здесь –

13

Для загрузки файла, мне нравится это намного лучше

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

Если файл открыт в Microsoft Word - есть ли способ создать поток памяти из этого файла? Я получаю сообщение об ошибке 'файл открывается другим процессом' – FrenkyB

+0

@FrenkyB Я также сталкиваюсь с этим много. Если вы открываете файл в Word или другом приложении, вы не можете этого сделать. Просто закройте файл в Word. – Kristopher

10

Сохранить в файл

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

нагрузки из файла

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

Первоначально реализация этого класса была размещена here

и

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

Я использую панель управления, чтобы добавить изображение или даже потоковое видео, но вы можете сохранить изображение на SQL Server как Изображение или MySQL как большойblob. Этот код работает для меня много. Проверьте это.

Здесь вы сохраните изображение

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

И здесь вы можете загрузить, но я использовал элемент управления PictureBox.

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

Надежда помогает.

16

Для тех, кто ищет для коротких версий:

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

File.WriteAllBytes("1.dat", memoryStream.ToArray()); 
Смежные вопросы