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

时间:2011-11-16 18:41:58

标签: c# filestream memorystream

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

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

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

9 个答案:

答案 0 :(得分:71)

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

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

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

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

答案 1 :(得分:10)

这里的其他答案很好,但是我认为一个非常深入的了解蒸汽作用的目的可能是有用的。下面的说明中有一些简化,但是希望这可以使您理解:

什么是流?

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

不好的比喻

想象一下一个海水淡化厂(一种吸收海水,去除盐分并向水网输出清洁饮用水的东西):

海水淡化厂无法一次从整个海洋中去除盐分(我们也不希望它……咸水鱼会住在哪里?),所以我们有了:

  • 一种SeaStream,一次吸取一定量的水到植物中。
  • SeaStream连接到DesalinationStream以除去盐
  • DesalinationStream的输出连接到DrinkingWaterNetworkStream,以将现在的无盐水输出到饮用水源。

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

一次移动大文件可能会出现问题

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

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

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

同样,如果数据源不可靠怎么办?从具有缓慢且不稳定的WiFi连接的网络驱动器中复制文件?一口气复制一个大文件可能会很令人生气,因为您会收到一半的文件,然后连接断开,并且必须重新开始,以免再次可能失败。

最好将文件拆分并一次移动一段

因此,与其一次获取整个文件,不如一次检索一个文件,然后一次将每个文件传递到目的地,这会更好。 Stream就是这样做的,这就是您提到的两种不同类型的流的来源:

  • 我们可以使用FileStream一次从一个文件中检索数据
  • ,数据库API可能会提供一个MemoryStream端点,我们可以一次写入一个端点。
  • 我们将这两个“管道”连接在一起,以将文件碎片从文件流到数据库。

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

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

流使我们可以从概念上消除中间的两个阶段,而不是立即将整个文件拖到计算机内存中,我们使用操作的输出来检索数据并将其直接传递给操作以传递数据进入数据库。

流的其他好处

像这样将数据的检索与数据的写入分开,也使我们能够执行检索数据和传递数据之间的动作。例如,我们可以添加一个加密阶段,或者可以将传入的数据写入一种以上类型的输出流(例如,到FileStream和NetworkStream)。

流还允许我们编写代码,以便在传输部分途中失败的情况下恢复操作。通过跟踪已移动的片段数,如果传输失败(例如,如果网络连接中断),我们可以从接收到最后一块的点重新开始Stream(这是offsetBeginRead方法中)。

答案 2 :(得分:7)

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

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

答案 3 :(得分:6)

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

答案 4 :(得分:5)

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

答案 5 :(得分:2)

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

答案 6 :(得分:0)

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

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

答案 7 :(得分:0)

关于stream本身,通常,这意味着当您将内容放入stream(内存)时,不会将任何数据源(文件,数据库...)正在与您合作,保存到内存。与数组或缓冲区相反,您可以将所有内容馈送到内存。在stream中,您会得到大块,例如。文件保存到内存。当您到达块的末尾时,stream将下一个块从文件传递到内存。当您仅迭代stream时,所有这些操作都会在低级背景下发生。因此,它被称为stream

答案 8 :(得分:0)

关于stream本身,通常,这意味着当您将内容放入stream(内存)时,不会将任何数据源(文件,数据库...)正在与您合作,保存到内存。与数组或缓冲区相反,您可以将所有内容馈送到内存。在stream中,您会得到大块,例如。文件保存到内存。当您到达块的末尾时,stream将下一个块从文件传递到内存。当您仅迭代stream时,所有这些操作都会在低级背景下发生。因此,它被称为stream