Сохранение и загрузка MemoryStream в / из файла

Я сериализую структуру в MemoryStream и хочу сохранить и загрузить сериализованную структуру.

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


person Mahdi Ghiasi    schedule 24.12.2011    source источник
comment
Если вам нужно сохранить в файл, почему вы используете MemoryStream?   -  person Oded    schedule 24.12.2011
comment
@Oded Что мне использовать? Вы можете привести мне пример?   -  person Mahdi Ghiasi    schedule 24.12.2011


Ответы (9)


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

memoryStream.WriteTo(fileStream);

Обновлять:

fileStream.CopyTo(memoryStream);
memoryStream.CopyTo(fileStream);
person kv-prajapati    schedule 24.12.2011
comment
memoryStream.CopyTo, похоже, не работал у меня, в то время как WriteTo работал. Я думаю, возможно, это было потому, что у меня memoryStream.Position не было 0 - person Mark Adamson; 09.07.2014
comment
Да, это правильно. Разница между ними в том, что CopyTo копирует из любой текущей позиции, а не всегда с начала, как это делает WriteTo. - person AnorZaken; 14.09.2015
comment
Добавление _1 _ перед CopyTo установит текущую позицию в 0, так что CopyTo скопирует весь поток. - person Martin Backasch; 14.11.2017
comment
Спасибо, вы сделали это так просто и всего в 2 строчки. - person Darpan Gupta; 10.06.2021

Предполагая, что имя 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 в FileStream):

using (FileStream file = new FileStream("file.bin", FileMode.Create, System.IO.FileAccess.Write))
    ms.CopyTo(file);
person Ashkan Mobayen Khiabani    schedule 24.12.2011
comment
Могу я спросить, почему вы используете FileMode.Create в образце чтения по сравнению с FileMode.Open? - person Philter; 14.02.2013
comment
В первом блоке кода вместо ручного копирования потока памяти в массив можно использовать встроенную функцию ms.ToArray(). - person Gman; 25.03.2013
comment
Важно установить ms.Position = 0, иначе массив байтов (и файл) будут содержать все нули. - person Gregory Khrapunovich; 05.11.2013
comment
@ Fernando68 конструкция using (...){ } имеет точно такой же эффект. - person Fabricio Araujo; 03.05.2017
comment
Так же, как предупреждение для других, использование (FileStream 'и' ms.CopyTo (file) 'устанавливает позицию в конец файла, и вам необходимо впоследствии сбросить поток памяти. - person Rebecca; 02.11.2018
comment
@GregoryKhrapunovich, это как кассета, пока мы ее создаем ... пишем до самого конца. Теперь необходимо перемотать ленту, прежде чем мы вставим ее в плеер. - person Paras Parmar; 02.02.2021

Поток действительно должен быть удален, даже если есть исключение (вполне вероятно, при файловом вводе-выводе) - мой любимый подход для этого - использование предложений, поэтому для записи вашего 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());
person Rob Church    schedule 07.02.2013

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

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

File.WriteAllBytes("1.dat", memoryStream.ToArray()); 
person Slai    schedule 22.11.2016

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

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

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

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

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

а также

[Serializable]
public class Car
{
    public string Name;
}
person Vadim Gremyachev    schedule 09.11.2015

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

MemoryStream ms = new MemoryStream();
using (FileStream fs = File.OpenRead(file))
{
    fs.CopyTo(ms);
}
person ProVega    schedule 10.10.2013
comment
Если файл открыт в Microsoft Word - есть ли способ создать поток памяти из этого файла? Я получаю сообщение об ошибке "файл открыт другим процессом" - person FrenkyB; 21.12.2013
comment
@FrenkyB Я тоже часто сталкиваюсь с этим. Если у вас открыт файл в Word или другом приложении, вы не сможете этого сделать. Просто закройте файл в Word. - person Kristopher; 10.11.2015
comment
@FrenkyB Можете ли вы сделать File.Copy? Я обнаружил, что это работает, затем прочитал из этого файла в поток и удалил новый файл ... ужасно, но, похоже, работает. - person ridecar2; 09.07.2019

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

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

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 Control.

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

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

person Leinad    schedule 06.10.2016

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

        }
    }
}

Использование :-

ImageWaterMarkBuilder.AddStream(stream).AddWaterMark("").CompileAndSave(filePath);
person Ragesh Punathil    schedule 27.04.2020