内存流和文件流的区别

本文关键字:区别 内存 文件 | 更新日期: 2023-09-27 18:14: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();
        }
    }
}

内存流和文件流的区别

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

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

现在它取决于你打算如何使用这两个。让我们假设您想要从数据库中读取二进制数据,您将使用MemoryStream。然而,如果你想在你的系统上读取一个文件,你会进入一个FileStream。

MemoryStream的一个优点是不需要在应用程序中创建临时缓冲区和文件。

这里的其他答案都很好,但我认为一个真正高层次地看待蒸汽服务的目的可能有用。在下面的解释中有一些简化,但希望这能让你理解这个想法:

什么是流?

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

开头的错误类比

想象一个海水淡化厂(吸收海水,去除盐分并向供水网络输出干净的饮用水):

海水淡化厂不能一次把海水中的盐全部除去(我们也不希望它这样做……咸水鱼住在哪里?),所以我们有:

  • 一次将一定量的水吸收到植物中的SeaStream
  • SeaStreamDesalinationStream脱盐
  • DesalinationStream的输出与DrinkingWaterNetworkStream相连接,将无盐的水输出到饮用水中。

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

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

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

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

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

同样,如果数据源不可靠,例如从WiFi连接缓慢且不稳定的网络驱动器复制文件,该怎么办?尝试一次复制一个大文件可能会让人恼火,因为你得到了一半的文件,然后连接断开,你必须重新开始,只是因为它可能再次失败。

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

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

  • 我们可以使用FileStream从一个文件中检索数据,每次一小块
  • 和数据库API可以提供一个MemoryStream端点,我们可以一次写入一块。
  • 我们将这两个"管道"连接在一起,使文件片段从文件流向数据库。

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

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

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

流的其他好处

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

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

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

通常,如果我需要一个流,我使用MemoryStream,但我不希望任何东西击中磁盘,我在向磁盘写入文件时使用FileStream。

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

在这个问题上有一个痛苦的经历,以下是我的发现。如果需要性能,应该将文件流的内容复制到内存流。我必须处理144个文件的内容,每个文件528kb,并将结果呈现给用户。大约花了250秒。(! !)。当我只是将每个文件流的内容复制到内存流时,(CopyTo方法)根本没有改变任何东西,时间下降到大约32秒。请注意,每次将一个流复制到另一个流时,流都附加在目标流的末尾,因此您可能需要在复制之前"倒带"它。希望能有所帮助。

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

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

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

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