MemoryStream을 파일에 저장 및로드


281

구조를 a로 직렬화하고 직렬화 된 구조 MemoryStream를 저장하고로드하려고합니다.

그렇다면 MemoryStream파일에 파일 을 저장하고 파일에서 다시로드하는 방법은 무엇입니까?


파일로 저장해야하는 경우 왜 MemoryStream?
Oded

@Oded 무엇을 사용해야합니까? 예를 들어 주시겠습니까?
Mahdi Ghiasi

답변:


365

메모리 스트림의 내용을 다른 스트림에 쓰는 데 MemoryStream.WriteTo또는 Stream.CopyTo프레임 워크 버전 4.5.2, 4.5.1, 4.5, 4에서 지원되는 방법을 사용할 수 있습니다 .

memoryStream.WriteTo(fileStream);

최신 정보:

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

13
memoryStream.CopyTo는 저에게는 효과가 없었지만 WriteTo는 작동하지 않았습니다. 아마도 내 memoryStream.Position이 0이 아니었기 때문일 것입니다.
Mark Adamson

10
네 맞습니다. 그들 사이의 차이점은 CopyTo가 항상 처음부터 WriteTo가 아닌 현재 위치가 무엇이든 CopyTo가 복사한다는 것입니다.
AnorZaken

6
[file|memory]Stream.Seek(0, SeekOrigin.Begin);before CopyTo를 추가 하면 현재 위치가 0으로 설정 CopyTo되어 전체 스트림이 복사됩니다.
Martin Backasch

264

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.Open에서 FileMode.Create를 사용하는 이유를 물을 수 있습니까?
Philter

6
첫 번째 코드 블록에서는 메모리 스트림을 수동으로 배열에 복사하는 대신 내장 ms.ToArray()기능을 사용할 수 있습니다 .
Gman

5
ms.Position = 0을 설정하는 것이 중요합니다. 그렇지 않으면 바이트 배열 (및 파일)에 모두 0이 포함됩니다.
Gregory Khrapunovich 21시 01 분

1
@ Fernando68 구조 using (...){ }는 정확히 동일한 효과를 갖습니다.
Fabricio Araujo

2
'(FileStream'및 'ms.CopyTo (file)'을 사용하는 다른 사람들에게 경고하는 것처럼 위치를 파일의 끝으로 설정하고 나중에 메모리 스트림을 재설정해야합니다.
Rebecca

64

스트림은 예외가있는 경우에도 실제로 처리해야합니다 (파일 I / O에서 매우 빠름). using 절이 가장 좋아하는 접근 방식이므로 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());

41

짧은 버전을 찾는 사람은 :

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

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

20

파일에 쓰기위한 결합 된 대답은 다음과 같습니다.

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

15

파일로 저장

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

14

파일을로드 할 때 나는 이것을 훨씬 좋아합니다.

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

파일이 Microsoft Word에서 열린 경우 해당 파일에서 메모리 스트림을 작성하는 방법이 있습니까? '다른 프로세스에서 파일을 열었습니다'라는 오류가 표시됩니다.
FrenkyB

@FrenkyB 나는 또한 이것에 많이 빠져 들었습니다. Word 또는 다른 응용 프로그램에서 파일을 열면 파일을 얻을 수 없습니다. Word에서 파일을 닫으십시오.
Kristopher 2018

@FrenkyB File.Copy를 할 수 있습니까? 작동한다는 것을 알았고 그 파일에서 스트림으로 읽고 새 파일을 삭제했습니다 ... 끔찍하지만 작동하는 것 같습니다.
ridecar2

3

패널 컨트롤을 사용하여 이미지를 추가하거나 비디오를 스트리밍 할 수도 있지만 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 컨트롤을 사용했습니다.

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

희망이 도움이됩니다.


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

        }
    }
}

사용법 :-

ImageWaterMarkBuilder.AddStream(stream).AddWaterMark("").CompileAndSave(filePath);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.