内存流和文件流的区别

Posted

技术标签:

【中文标题】内存流和文件流的区别【英文标题】:difference between memory stream and filestream 【发布时间】:2011-12-30 17:02:57 【问题描述】:

在序列化过程中,我们可以使用内存流或文件流。

这两者之间的基本区别是什么?内存流是什么意思?

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

【问题讨论】:

【参考方案1】:

关于stream本身,一般来说,这意味着当你将一个内容放入stream(内存)时,它不会将任何数据源(文件,db...)的所有内容都放入你正在使用,记忆。与例如数组或缓冲区相反,您将所有内容放入内存。在stream 中,您会得到一个chunk 例如。文件到内存中。当你到达块的末尾时,stream 从文件获取下一个块到内存。这一切都发生在低级背景中,而您只是在迭代 stream。这就是为什么它被称为stream

【讨论】:

【参考方案2】:

这里的其他答案很棒,但我认为对蒸汽服务的目的进行非常高层次的了解可能会有用。在下面的解释中进行了一些简化,但希望这能传达出这个想法:

什么是流?

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

一个不好的类比开始

想象一个海水淡化厂(吸收海水、去除盐分并将清洁的饮用水输出到水网):

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

SeaStream 一次将一定量的水吸入植物。 那个SeaStream连接到DesalinationStream去盐分 DesalinationStream 的输出连接到DrinkingWaterNetworkStream,将现在的无盐水输出到饮用水源。

好的,那这和电脑有什么关系?

一次移动所有大文件可能会有问题

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

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

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

同样,如果数据源不可靠,例如使用缓慢且不稳定的 WiFi 连接从网络驱动器复制文件?尝试一次性复制一个大文件可能会令人恼火,因为您获得了一半的文件,然后连接断开,您必须重新开始,否则它可能会再次失败。

最好是拆分文件,一次移动一块

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

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

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

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

Streams 允许我们在概念上取消中间两个阶段,而不是一次将整个文件拖到计算机内存中,我们将操作的输出用于检索数据并将其直接通过管道传递给操作以传递数据到数据库中。

流的其他好处

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

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

【讨论】:

谢谢! “数据库 API 可能提供 MemoryStream 端点”是我试图理解使用 MemoryStream 写入控制台的说明。【参考方案3】:

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

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

【讨论】:

【参考方案4】:

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

【讨论】:

痛苦的经历?!?当然,在 RAM 中操作文件将比在磁盘上操作文件更快。你期待什么? ;-)【参考方案5】:

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

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

现在取决于您打算如何使用这两种方法。例如:假设您想从数据库中读取二进制数据,您将使用 MemoryStream。但是,如果您想读取系统上的文件,则需要使用 FileStream。

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

【讨论】:

既然对象已经在内存中了,为什么还要为序列化分配内存流呢? 因为内存流将对象作为字节序列来操作,而不是作为其逻辑程序的“意义”。 @tudor:因为我是.net 的新手,你能简要解释一下吗? @Raghav55:一个对象可以简化为一个字节序列,对吗?在您的程序逻辑中,该对象具有含义,例如持有姓名、地​​址等信息的人员。这就是该对象在您的程序中的显示方式。当您将其序列化为内存流时,它会减少为没有意义的字节流。它仅被存储,但对您的程序逻辑没有实际价值。 我正在从数据库中读取大量日期并希望将其作为 csv 文件发送回用户,但我使用内存流的内存不足...我相信我'将不得不将其转换为文件流以获得更多空间。【参考方案6】:

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

【讨论】:

嗨克里斯托弗,想在这里问一个问题。那么这是否意味着如果我使用内存流,模式是“不是从文件产生的数据(例如fprintf(memory_buf, "hello"))内存缓冲区过程数据”,而对于基于文件的流,模式是“数据位于/产生/来自磁盘内存缓冲区过程数据”?【参考方案7】:

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

【讨论】:

在对大数据进行序列化时哪个更好?如果序列化数据很大并且可用内存很小。当我们使用内存流时,这种情况会发生什么? 如果你的数据超过了可用内存,它最终会开始分页到磁盘。这很糟糕,因为整个系统的性能会下降。在这种情况下,最好只流式传输到文件。【参考方案8】:

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

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

【讨论】:

以上是关于内存流和文件流的区别的主要内容,如果未能解决你的问题,请参考以下文章

Java面试题|输入流和输出流的区别

使用IO流复制文件夹(包括子目录)

Java字符流和字节流对文件操作的区别

关于IO流中的输入流输出流的理解

Io流的概述

WebRTC[37]-WebRTC中自定义大小流和 simulcast 流的区别