C# 使用流
Posted
技术标签:
【中文标题】C# 使用流【英文标题】:C# using streams 【发布时间】:2010-11-27 02:52:33 【问题描述】:流对我来说有点神秘。我不知道何时使用哪个流以及如何使用它们。有人可以向我解释一下流是如何使用的吗?
如果我理解正确的话,有三种流类型:
stream
read stream
write stream
这是正确的吗?例如,Memorystream
和 FileStream
之间有什么区别?
【问题讨论】:
你可能想检查***.com/questions/507747/… 获取一个字节数组,然后为其创建一个包装器 (Stream
),它公开了一些有用的方法,例如读取、写入和更改位置。现在,您可以基于继承自 Stream
的后备存储(FileStream、MemoryStream)创建类,并基于特定的后备存储构建该功能。
【参考方案1】:
流是用于传输数据的对象。有一个通用流类System.IO.Stream
,.NET 中的所有其他流类都从该类派生。 Stream
类处理字节。
具体的流类用于处理字节以外的其他类型的数据。例如:
FileStream
类在外部源是文件时使用
MemoryStream
用于在内存中存储数据
System.Net.Sockets.NetworkStream
处理网络数据
StreamReader
和 StreamWriter
等读取器/写入器流不是流 - 它们不是从 System.IO.Stream
派生的,它们旨在帮助从流中写入和读取数据!
【讨论】:
所以,如果我理解正确,流包含数据并且不会对它做任何事情。 reader 和 writer 'helper' 类可以处理(操作)流中的数据吗? 不,Stream不是数据容器,它是用来传输数据的,例如FileStream将数据从byte[]传输到物理文件,NetworkStream通过socket传输byte[]。 Reader Writer 类是用于从流中写入和读取的辅助类,例如 StreamReader 可用于从 Stream 字符串而不是 byte[] 中读取。如果您将 FileStream 作为参数,它将从 File 中读取,如果 NetworkStream 来自套接字。 另外,StreamReader 和 StreamWriter 用于读写 TEXT(字符)流。 有一篇很好的文章可以帮助你理解 MemoryStream。 codeproject.com/Articles/832387/… @user420667。好问题。在 Audiostream 和 TemperatureStream 情况下,它们很可能是与设备关联的驱动程序的 BinaryStreams。或者,您可以创建一个专门为接口构建的 CustomStream。【参考方案2】:为了在此处扩展其他答案,并帮助解释您将看到的许多示例代码,大多数情况下您不会直接读取和写入流。流是传输数据的低级方式。
您会注意到读取和写入的函数都是面向字节的,例如写字节()。没有用于处理整数、字符串等的函数。这使得流非常通用,但如果您只想传输文本,则使用起来就不那么简单了。
但是,.NET 提供了在本机类型和低级流接口之间转换的类,并为您将数据传输到流或从流中传输。一些值得注意的此类是:
StreamWriter // Badly named. Should be TextWriter.
StreamReader // Badly named. Should be TextReader.
BinaryWriter
BinaryReader
要使用这些,首先获取流,然后创建上述类之一并将其与流相关联。例如
MemoryStream memoryStream = new MemoryStream();
StreamWriter myStreamWriter = new StreamWriter(memoryStream);
StreamReader 和 StreamWriter 在本机类型及其字符串表示之间进行转换,然后将字符串作为字节传入和传出流。所以
myStreamWriter.Write(123);
会将“123”(三个字符“1”、“2”然后是“3”)写入流。如果您正在处理文本文件(例如 html),StreamReader 和 StreamWriter 是您将使用的类。
而
myBinaryWriter.Write(123);
将写入代表 32 位整数值 123 的四个字节(0x7B、0x00、0x00、0x00)。如果您正在处理二进制文件或网络协议 BinaryReader 和 BinaryWriter 是您可能使用的。 (如果您要与网络或其他系统交换数据,则需要注意endianness,但这是另一篇文章。)
【讨论】:
StreamWriter 和 Reader 适配器类的命名严重错误。谢谢你提到这一点。他们怎么会想出这个名字仍然让我感到惊讶。 另外,即使是二进制的 writer 和 reader 类的命名也很糟糕。【参考方案3】:流非常适合处理大量数据。当同时将所有数据加载到内存中不切实际时,您可以将其作为流打开并处理其中的一小部分。
【讨论】:
希望看到您刚才所说的“使用小块工作”的示例。 流也适用于少量数据。如果 C# 程序员想要操作文件的内容,他/她必须使用流,而不管数据量如何。同样的说法也适用于网络流。诚然,如果程序员正在编写像 C 这样的低级语言,那么可以直接将字符或字节写入磁盘或套接字,但即使是少量数据,也很耗时且更容易出现错误。【参考方案4】:Stream 只是physical
字节流的抽象(或包装)。这个physical
流称为base stream
。所以总是有一个基础流,在其上创建一个流包装器,因此包装器以基础流类型命名,即FileStream
、MemoryStream
等。
流包装器的优点是您可以获得一个统一的 api 来与任何底层类型的流进行交互 usb, file
等。
为什么要将数据视为流 - 因为数据块是按需加载的,我们可以将数据作为块进行检查/处理,而不是将整个数据加载到记忆。这是大多数程序处理大文件的方式,例如加密操作系统映像文件。
【讨论】:
【参考方案5】:我将从阅读 MSDN 上的流开始: http://msdn.microsoft.com/en-us/library/system.io.stream.aspx
Memorystream 和 FileStream 分别是用于处理原始内存和文件的流...
【讨论】:
感谢您的链接。我喜欢“您可以在线浏览源代码,下载参考以供离线查看,并在调试期间逐步浏览源代码(包括补丁和更新)”。此功能提供了新的洞察力。【参考方案6】:Stream
只有一种基本类型。然而,在各种情况下,一些成员在调用时会抛出异常,因为在这种情况下操作不可用。
例如,MemoryStream
只是一种将字节移入和移出内存块的方法。因此,您可以在其上调用 Read 和 Write。
另一方面,FileStream
允许您从文件读取或写入(或两者)。您是否可以实际读取或写入取决于文件的打开方式。如果您仅以读取权限打开文件,则无法写入文件。
【讨论】:
【参考方案7】:我不会称这些不同类型的流。 Stream 类具有 CanRead 和 CanWrite 属性,它们告诉您是否可以读取和写入特定流。
不同流类(例如 MemoryStream 与 FileStream)之间的主要区别在于后备存储 - 数据从哪里读取或写入到哪里。从名字上看就很明显了。 MemoryStream 仅将数据存储在内存中,FileStream 由磁盘上的文件支持,NetworkStream 从网络读取数据等等。
【讨论】:
以上是关于C# 使用流的主要内容,如果未能解决你的问题,请参考以下文章
c#:如何使用 httpclient 发布异步请求并获取流?