【问题标题】:Save and load MemoryStream to/from a file将 MemoryStream 保存到文件或从文件加载
【发布时间】:2012-01-27 06:52:50
【问题描述】:

我正在将一个结构序列化为MemoryStream,我想保存并加载序列化的结构。

那么,如何将MemoryStream 保存到文件中并从文件中加载回来?

【问题讨论】:

  • 如果你需要保存到一个文件,你为什么使用MemoryStream
  • @Oded 我应该使用什么?可以举个例子吗?

标签: c# file io stream memorystream


【解决方案1】:

您可以使用MemoryStream.WriteToStream.CopyTo(框架版本4.5.2、4.5.1、4.5、4 支持)方法将内存流的内容写入另一个流。

memoryStream.WriteTo(fileStream);

更新:

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

【讨论】:

  • memoryStream.CopyTo 似乎对我不起作用,而 WriteTo 起作用。我想可能是因为我的 memoryStream.Position 不是 0
  • 是的,这是正确的。它们之间的区别在于 CopyTo 从当前位置复制,而不是像 WriteTo 那样总是从头开始复制。
  • CopyTo 之前添加[file|memory]Stream.Seek(0, SeekOrigin.Begin); 会将当前位置设置为0,这样CopyTo 将复制完整的流。
  • 谢谢。你让它变得如此简单,只用了 2 行。
【解决方案2】:

假设 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);

【讨论】:

  • 我能问一下你为什么在读取示例中使用 FileMode.Create vs FileMode.Open 吗?
  • 在第一个代码块中,您可以使用内置的ms.ToArray()函数,而不是手动将内存流复制到数组中。
  • 设置 ms.Position = 0 很重要,否则字节数组(和文件)将包含全零。
  • @Fernando68 构造 using (...){ } 具有完全相同的效果。
  • 就像对其他人的警告'使用(FileStream'和'ms.CopyTo(file)'将位置设置为文件末尾,之后您需要重置内存流。
【解决方案3】:

即使存在异常(很可能在文件 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());

【讨论】:

    【解决方案4】:

    对于寻找简短版本的任何人:

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

    【讨论】:

      【解决方案5】:

      写入文件的组合答案可以是;

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

      【讨论】:

        【解决方案6】:

        保存到文件中

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

        【讨论】:

          【解决方案7】:

          对于加载文件,我更喜欢这个

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

          【讨论】:

          • 如果在 Microsoft Word 中打开文件 - 有没有办法从该文件创建内存流?我收到错误“文件已被另一个进程打开”
          • @FrenkyB 我也经常遇到这种情况。如果您在 Word 或其他应用程序中打开了文件,那么您将无法执行此操作。只需在 Word 中关闭文件即可。
          • @FrenkyB 你能做一个 File.Copy 吗?我发现它可以工作,然后从该文件中读取到流中并删除新文件......可怕,但似乎工作。
          【解决方案8】:

          我使用面板控件来添加图像甚至流式视频,但您可以将图像保存在 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);
          

          希望有所帮助。

          【讨论】:

            【解决方案9】:
            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);
            

            【讨论】:

              猜你喜欢
              • 2013-09-16
              • 2014-10-04
              • 2022-06-29
              • 2010-10-21
              • 1970-01-01
              • 2019-05-15
              • 2013-02-06
              • 2013-03-24
              • 1970-01-01
              相关资源
              最近更新 更多