IO 101:TextWriter、FileStream 和 StreamWriter 之间的主要区别是啥?
Posted
技术标签:
【中文标题】IO 101:TextWriter、FileStream 和 StreamWriter 之间的主要区别是啥?【英文标题】:IO 101: Which are the main differences between TextWriter, FileStream and StreamWriter?IO 101:TextWriter、FileStream 和 StreamWriter 之间的主要区别是什么? 【发布时间】:2010-11-03 21:03:58 【问题描述】:首先让我道歉,如果这个问题对于你们当中经验丰富的程序员来说可能听起来有点业余,问题是我在工作中对此有很多争论,所以我真的很想弄清楚这一点,这基本上就是为什么我'我依靠 *** 社区来一劳永逸地解决这个问题:)
所以,一方面根据 MSDN,我们有:
TextWriter 类
代表一个可以写一个 连续的一系列字符。这 类是抽象的。
文件流类
在文件周围暴露一个流, 支持同步和 异步读写 操作。
StreamWriter 类
实现一个 TextWriter 用于写作 字符到特定的流中 编码。
另一方面,很明显它们都属于 System.IO,但考虑到 MSDN 示例混合了其中的一些,我仍然没有达到非常想要的 a-ha 时刻。
任何评论都将不胜感激,在此先感谢!
【问题讨论】:
好问题,这不一定是维基,我觉得顺便说一句。 【参考方案1】:Streams 处理 bytes,Writers 处理 characters。
字节 != 字符。一个字符可能需要超过一个字节来表示。从字符到字节的映射称为编码。
FileStream
指的是写入文件的字节,类似于MemoryStream
指的是写入内存缓冲区的字节。为了将字符写入流,您需要将它们转换为字节串。这就是StreamWriter
发挥作用的地方。它需要一个字符序列和一个编码,然后将其转换为一个字节序列。
TextWriter
是所有 Writer 必须遵守的接口(嗯,抽象基类)。它具有基于字符的所有操作。 bytes 的等价物是 Stream
抽象基类。
事情也朝着相反的方向发展。有一个 TextReader
抽象基类,描述如何从某个地方读取字符,还有一个 StreamReader
,它允许您从提供编码的面向字节的流中读取字符 - 但这次反过来使用,以聚合任何在适当的情况下将多字节序列转换为单个字符。
Stream
可用于读取和写入,因为字节是 I/O 操作中使用的最低级别项。
【讨论】:
TextWriter 不是一个接口,它是一个抽象基类。 非常感谢 lavinio 的评论!在这种特殊情况下,我试图解决我必须处理 BLOB,即读取数据库字段然后写入磁盘,反之亦然,所以我猜 Streams 是要走的路? 从文件中提取到 BLOB 可能是二进制操作,所以是的,流是要走的路。如果周围有 CLOB,那么您可能想要使用 Reader/Writer 类。【参考方案2】:我一直认为最好的办法就是看看它们提供了哪些方法以及如何构建它们。这几乎总是我在使用 API 时最关心的事情,如果不是唯一的话。我如何构建它,它可以做什么?
您不能实例化 TextWriter。很抽象。这告诉我它服务的唯一真正目的是抽象。如果您编写的函数将任何类型的 writer 作为参数,则很有可能您应该让 TextWriter 更加通用。
您可以实例化一个 StreamWriter,它会按照它所说的去做,它会写入流。这意味着它需要一个流来完成任何真正的写入。不过,一旦你有了那个流,你就可以做各种简洁的事情,比如一次写一整行,而不是像直接在流上那样处理单个字符(或者更确切地说是字节)。
所以基本上,你会得到一个流,这样你就可以将它提供给 StreamWriter(或 Reader)。如果您正在编写文本,您可能不想直接使用流,只想使用字符数组而不是字符串。
FileStreams 可以方便地直接从 File 和 FileInfo 类中实例化,在我的使用中,这就是它们通常的实例化方式。获取一个文件(我喜欢使用 FileInfo)并调用 OpenWrite()。将它传递给 StreamWriter(它只是一种 TextWriter),然后您就可以使用了。
概括:当您想找出一个类时,请尝试查看您如何实例化它以及它可以做什么。这通常会清除很多。
【讨论】:
非常感谢丹尼尔的建议,这真的很有帮助!【参考方案3】:“Stream”和“Writer/Reader”之间有明显的区别。
流是字节级别的表示,实际上是一个可以以多种方式实现的抽象概念。例如,您有一个 FileStream 和一个 MemoryStream。两者都是字节流,但存储方式不同。
Writers 和 Readers 为您提供了一种处理流、从中添加和提取数据的方法。
对于您的特定示例,TextWriter 是一个将字符顺序写入流的抽象类。它有几个实现(StreamWriter、StringWriter)在不同的上下文中很有用。您将使用当时有意义的任何一种。然而,对于几个 API,所需要的只是一个 TextWriter,或者可以在其上调用“Write”或“WriteLine”的东西。如果您的编写器用于将内容放入字符串、任意内存或文件中,这些 API 就不必担心。
【讨论】:
【参考方案4】:FileStream 类管理获取文件的句柄并打开它以进行读取或写入以及其他文件系统功能。 BinaryWriter 将二进制数据写入流,StreamWriter 将字符数据写入流。它们都可以使用 FileStream 对象将二进制或字符数据写入文件。
TextWriter 是 StreamWriter 继承自的基类。 TextWriter 旨在获取一个类型并使用其Write 方法输出一个字符串。 StreamWriter 的 TextWriter.Write 方法实现将字符串或字符数据写入流。 BinaryWriter 不继承 TextWriter 因为它不会将字符数据写入流。
【讨论】:
【参考方案5】:Stream
是一个抽象基类,代表一系列字节。
MemoryStream
是保存在内存中的字节流,由数组支持。
FileStream
是文件中的字节流,通常由磁盘上某处的文件句柄支持。
文本字符本身由字节组成,单个字符可以是多个字节,具体取决于编码。有一些标准类使用特定的编码读取和写入不同来源的文本。
TextWriter
是一个抽象基类,用于将文本字符写入目标。
StreamWriter
将文本字符(转换为字节)写入字节流。
StringWriter
将文本字符写入字符串(通过 StringBuilder)。
TextReader
是一个抽象基类,用于从源中读取文本字符。
StreamReader
从字节流中读取文本字符(从字节转换而来)。
StringReader
从字符串中读取文本字符。
Stream
、TextWriter
、TextReader
都是抽象基类,因此它们从不直接使用,而是通过类似上述的实现来使用。但是,您将在方法定义中看到基类,以便可以使用不同的实现,包括您自己的自定义实现(如果需要)。抽象类类似于接口,但实际上可以定义方法的逻辑,可以重复使用,而无需每个实现都重复相同的基本代码。
【讨论】:
以上是关于IO 101:TextWriter、FileStream 和 StreamWriter 之间的主要区别是啥?的主要内容,如果未能解决你的问题,请参考以下文章
Azure Webjob TextWriter 记录器被放置在我的方法中间
C#流总结(文件流内存流网络流BufferedStreamStreamReader/StreamWriterTextReader/TextWriter)
C#流总结(文件流内存流网络流BufferedStreamStreamReader/StreamWriterTextReader/TextWriter)