IO 101:TextWriter、FileStream和StreamWriter之间的主要区别是什么?

44

首先,如果这个问题对于经验丰富的程序员来说听起来有些业余,请允许我道歉。事实是,我在工作中一直在争论这个问题,所以我真的想搞清楚这个问题,这就是为什么我依靠Stackoverflow社区来最终解决这个问题的原因 :)

因此,根据MSDN的说法,我们有:

TextWriter类

表示可以写入连续一系列字符的编写器。此类是抽象的。

FileStream类

公开一个环绕文件的流,支持同步和异步读取和写入操作。

StreamWriter类

实现了一个TextWriter,用于按特定编码将字符写入流中。

另一方面,显然它们都属于System.IO,但是由于MSDN示例有些混合使用它们,因此我仍然没有达到期望的“灵光一闪”。

非常感谢您的任何评论!提前多谢了!


很好的问题,我觉得这不需要成为维基百科。 - nawfal
5个回答

70

流处理字节,写入器处理字符。

字节不等于字符。一个字符可能需要多个字节来表示。从字符到字节的映射称为编码。

FileStream指的是写入文件的字节,类似于MemoryStream指的是写入内存缓冲区的字节。要将字符写入流中,需要将它们转换为一串字节的字符串。这就是StreamWriter的作用。它接受一系列字符和一个编码,并将其转换为一系列字节。

TextWriter是一个接口(或抽象基类),所有的写入器都必须遵循该接口。它的所有操作都基于字符。字节的对应项是Stream抽象基类。

事物也可以朝相反的方向进行。有一个TextReader抽象基类,描述了如何从某个地方读取字符,还有一个StreamReader,允许您从提供编码的面向字节的流中读取字符——但这次是反过来的,将任何多字节序列聚合成适当的单个字符。

Stream可用于读取和写入,因为字节是I/O操作中使用的最低级别的项。


6
TextWriter 不是一个接口,而是一个抽象基类。 - scottm
1
非常感谢您的评论,lavinio!在这种特殊情况下,我需要处理BLOBs,即读取数据库字段然后写入磁盘,反之亦然,所以我想流是正确的选择? - Nano Taboada
从文件中读取到 BLOB 可能是一个二进制操作,所以是的,流是正确的选择。如果有 CLOB 存在,则可能需要使用 Reader/Writer 类。 - lavinio

10

我一直觉得最好的方法就是看看它们提供了哪些方法以及如何构建它们。当使用API时,这几乎总是我关心的主要事情,如果不是唯一的事情。我该如何构建它并且它能做什么?

你无法实例化TextWriter。它是抽象的。这告诉我它的唯一真正目的就是抽象。如果你编写一个需要任何类型写入器作为参数的函数,那么很可能应该选择更通用的TextWriter。

StreamWriter可以被实例化,并且它恰好做了它所说的——写入流。这意味着它将需要一个流来进行任何真正的写入。不过,一旦你拥有了那个流,你可以做各种各样的有趣的事情,比如一次写整行而不必像你直接在流上处理单个字符(或字节)那样。

因此,基本上,你获取一个流,以便可以将其提供给StreamWriter(或Reader)。如果你正在写文本,你可能不想直接使用流,就像你不想使用字符数组而不是字符串一样。

FileStreams可以方便地直接从File和FileInfo类中实例化,在我的使用中,这通常是它们被实例化的方式。获取一个文件(我喜欢使用FileInfo)并调用OpenWrite()。将它传递给StreamWriter(它只是TextWriter的一种类型),你就可以开始了。

总之:当你想弄清一个类时,试着看看你如何实例化它以及它能做什么。这通常可以解决很多问题。


1
非常感谢你的建议,Daniel。它真的很有启发性! - Nano Taboada

6

“Stream”和“Writer/Reader”之间有明显的区别。

流是一个字节级的表示,它是一个抽象的概念,可以用各种方式实现。例如,你有FileStream和MemoryStream,这两个都是字节流,但它们存储方式不同。

编写器和读取器为您提供了一种处理流的方法,从中添加和提取数据。

对于您特定的示例,TextWriter是一个抽象类,按顺序将字符写入流中。它有几种实现(StreamWriter、StringWriter),适用于不同的上下文。在某些API中,只需要一个TextWriter或某些东西调用“Write”或“WriteLine”。如果您的编写器用于将内容放入字符串、任意内存或文件中,这不是这些API的问题。


5

Stream是一个抽象基类,表示一系列字节。

  • MemoryStream是保存在内存中的一系列字节,由数组支持的流。

  • FileStream是文件中的一系列字节,通常由磁盘上某个文件句柄支持的流。

文本字符本身由字节组成,单个字符可以是多个字节,这取决于编码。有一些标准类可以使用特定编码读写文本到不同的源。

TextWriter是一个将文本字符写入目标的抽象基类。

  • StreamWriter将文本字符(转换为字节)写入一系列字节的流。
  • StringWriter将文本字符写入一个字符串(通过StringBuilder)。

TextReader是从源读取文本字符的抽象基类。

  • StreamReader从一系列字节的流读取文本字符(从字节转换而来)。
  • StringReader从一个字符串中读取文本字符。

StreamTextWriterTextReader都是抽象基类,因此它们永远不会被直接使用,而是通过上述实现来使用。但是,在方法定义中可以看到这些基类,以便可以使用不同的实现,包括自己的自定义实现(如果需要)。抽象类类似于接口,但实际上可以定义方法的逻辑,这些方法可以在不重复基本代码的情况下重复使用。


4

FileStream类用于管理获取文件句柄、打开文件以进行读写和其他文件系统功能。BinaryWriter将二进制数据写入流中,而StreamWriter则将字符数据写入流中。它们都可以使用FileStream对象将二进制或字符数据写入文件。

TextWriter是StreamWriter继承的基类。TextWriter旨在使用其Write方法接收类型并输出字符串。StreamWriter的TextWriter.Write方法实现将字符串或字符数据写入流中。BinaryWriter不继承TextWriter,因为它不会将字符数据写入流中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接