内存流和文件流之间的差异

问题描述 投票:46回答:7

在序列化期间,我们可以使用内存流或文件流。

这两者之间的基本区别是什么?记忆流意味着什么?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization.Formatters.Binary;

namespace Serilization
{
    class Program
    {
        static void Main(string[] args)
        {
            MemoryStream aStream = new MemoryStream();
            BinaryFormatter aBinaryFormat = new BinaryFormatter();
            aBinaryFormat.Serialize(aStream, person);
            aStream.Close();
        }
    }
}
c# filestream memorystream
7个回答
76
投票

Stream是字节的表示。这两个类都派生自Stream类,它是抽象的定义。

顾名思义,FileStream读取和写入文件,而MemoryStream读取和写入内存。因此它与存储流的位置有关。

现在,这取决于您计划如何使用这两者。例如:假设您想要从数据库中读取二进制数据,您将进入MemoryStream。但是,如果要读取系统上的文件,则可以使用FileStream。

MemoryStream的一个快速优势是无需在应用程序中创建临时缓冲区和文件。


14
投票

这里的其他答案都很棒,但我认为一个真正高水平看一下蒸汽用途的目的可能是有用的。在下面的解释中有一些简化,但希望这可以解决这个问题:

什么是流?

流实际上是两个地方之间的数据流,它是管道而不是管道的内容。

一个糟糕的比喻开始

想象一下一个海水淡化厂(需要海水,去除盐并向水网输出干净的饮用水):

海水淡化厂不能同时从所有海洋中除去盐(我们也不希望它......咸水鱼会在哪里居住?),所以我们有:

  • 一个SeaStream一次吸入一定量的水进入植物。
  • SeaStream连接到DesalinationStream去除盐
  • DesalinationStream的输出与DrinkingWaterNetworkStream连接,将现在无盐的水输出到饮用水供应。

好的,那与计算机有什么关系呢?

Moving big files all at once can be problematic

经常在计算中我们想要在两个位置之间移动数据,例如从外部硬盘驱动器到数据库中的二进制字段(使用另一个答案中给出的示例)。我们可以通过将文件中的所有数据从位置A复制到计算机的内存中并从那里复制到位置B,但是如果文件很大或者源或目标可能不可靠,那么立即移动整个文件可能无论是不可行还是不明智。

例如,假设我们要将USB记忆棒上的大文件移动到数据库中的字段。我们可以使用'System.IO.File'对象将整个文件检索到计算机的内存中,然后使用数据库连接将该文件传递到数据库。

但是,这可能存在问题,如果文件大于计算机的可用RAM会怎么样?现在该文件可能会缓存到硬盘驱动器上,这很慢,甚至可能会使计算机速度降低。

同样,如果数据源不可靠,例如,从具有缓慢和片状WiFi连接的网络驱动器复制文件?试图一次性复制一个大文件可能会令人愤怒,因为你获得了一半的文件,然后连接断了,你必须重新开始,只是因为它可能再次失败。

It can be better to split the file and move it a piece at a time

因此,不是一次获取整个文件,最好一次检索一个文件并一次将每个文件传递到目标文件。这就是Stream所做的,这就是你提到的两种不同类型的流进来的地方:

  • 我们可以使用FileStream一次从一个文件中检索数据
  • 并且数据库API可以提供MemoryStream端点,我们可以一次写入一个部分。
  • 我们将这两个“管道”连接在一起,将文件从文件传输到数据库。

即使文件不是太大而无法保存在RAM中,如果没有流,我们仍然在做一些我们不需要的数字或读/写操作。我们正在进行的阶段是:

  1. 从磁盘检索数据(慢)
  2. 写入计算机内存中的File对象(快一点)
  3. 从计算机内存中的File对象读取(再次更快)
  4. 写入数据库(可能很慢,因为在该管道末端可能存在旋转磁盘硬盘驱动器)

Streams允许我们在概念上取消中间两个阶段,而不是立即将整个文件拖入计算机内存,我们采取操作的输出来检索数据并直接管道操作以将数据传递到数据库。

流的其他好处

将数据的检索与这样的数据写入分开也允许我们在检索数据和传递数据之间执行操作。例如,我们可以添加加密阶段,或者我们可以将输入数据写入多种类型的输出流(例如,写入FileStream和NetworkStream)。

Streams还允许我们编写代码,如果传输失败,我们可以恢复操作。通过跟踪我们移动的块数,如果传输失败(例如,如果网络连接断开),我们可以从我们收到最后一块的点重新启动Stream(这是offset方法中的BeginRead) )。


8
投票

在最简单的形式中,MemoryStream将数据写入内存,而FileStream将数据写入文件。

通常情况下,如果我需要一个流,我会使用MemoryStream,但是我不希望任何东西碰到磁盘,并且在将文件写入磁盘时使用FileStream。


6
投票

当文件流从文件读取时,存储器流可用于读取映射在计算机内部存储器(RAM)中的数据。您基本上是从内存中读取/写入字节流。


5
投票

在这个问题上有一个痛苦的经历,这是我发现的。如果需要性能,则应将文件流的内容复制到内存流。我必须处理144个文件的内容,每个文件528k字节,并向用户呈现结果。 aprox需要250秒。 (!!!!)。当我只是将每个文件流的内容复制到内存流(CopyTo方法)而根本没有改变任何内容时,时间下降到大约32秒。请注意,每次将一个流复制到另一个流时,流都会附加到目标流的末尾,因此您可能需要在复制到它之前“回滚”它。希望能帮助到你。


2
投票

内存流通过内存缓冲区处理数据。文件流处理磁盘上的文件。


0
投票

在我看来,在内存中序列化对象几乎没有任何用处。如果要将对象保存在磁盘上,则需要序列化对象。通常,序列化是从对象(在内存中)到磁盘完成的,而反序列化是从保存的序列化对象(在磁盘上)到对象(在内存中)完成的。

因此,大多数情况下,您希望序列化到磁盘,因此您使用Filestream进行序列化。

© www.soinside.com 2019 - 2024. All rights reserved.