C#使用流


116

溪流对我来说有点神秘。我不知道何时使用哪个流以及如何使用它们。有人可以向我解释如何使用流吗?

如果我理解正确,则有三种流类型:

  • stream
  • read stream
  • write stream

这样对吗?并且,例如,a Memorystream和a有FileStream什么区别?



3
取一个字节数组,然后为其创建包装器(Stream),该包装器提供了一些有用的方法,例如读取,写入和更改位置。现在,您可以基于其后备存储(FileStream,MemoryStream)创建类,这些类从Stream特定后备存储继承并建立在该功能的基础上。
松饼人

Answers:


80

是用于传输数据的对象。有一个通用的流类System.IO.Stream,.NET中的所有其他流类都从该类派生。在Stream类的字节交易。

具体的流类用于处理字节以外的其他类型的数据。例如:

  • FileStream当外部源是一个文件类用于
  • MemoryStream 用于将数据存储在内存中
  • System.Net.Sockets.NetworkStream 处理网络数据

读取器/写入器流,例如StreamReaderStreamWriter不是流-它们不是从派生的System.IO.Stream,它们旨在帮助在流中读写数据!


3
因此,如果我正确理解,流将包含数据,并且对此不执行任何操作。读取器和写入器的“帮助器”类可以处理(操纵)流中的数据吗?
马丁于2009年

9
不,Stream不是数据容器,它用于传输数据,例如FileStream将数据从byte []传输到物理文件,NetworkStream通过套接字传输byte []。Reader Writer类是用于从流写入和读取的辅助类,例如StreamReader可用于从流字符串而不是byte []读取。如果将FileStream用作参数,则从File读取,如果从套接字读取NetworkStream。
Arsen Mkrtchyan

另外,StreamReader和StreamWriter用于读取和写入TEXT(字符)流。
1c1cle 2015年

1
有一篇很好的文章可以帮助您了解MemoryStream。codeproject.com/Articles/832387/...
夹脊李

2
@ user420667。好问题。在AudioStream和TemperatureStream情况下,它们很可能是与设备关联的驱动程序的BinaryStreams。或者,您可以创建专门为该接口构建的CustomStream。
1c1cle

62

为了在此处进一步扩展其他答案,并帮助解释很多您会看到的示例代码,大多数情况下,您不直接对流进行读写。流是传输数据的底层方法。

您会注意到,用于读取和写入的函数均以字节为单位,例如WriteByte()。没有用于处理整数,字符串等的函数。这使流非常通用,但如果您仅想传输文本,则处理起来就不那么容易了。

但是,.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。(如果要与网络或其他系统交换数据,则需要注意字节序,但这是另一篇文章。)


StreamWriter和Reader适配器类的名称严重错误。感谢您提及。他们是怎么想到这个名字的,这仍然令我感到惊讶。
塔里克

同样,甚至二进制的writer和reader类也被错误命名。
塔里克

22

流非常适合处理大量数据。如果无法同时将所有数据加载到内存中,则可以将其作为流打开并使用其中的小块。


1
希望看到您刚才所说的“小块工作”的例子。
珍娜·叶

2
流也适用于少量数据。如果C#程序员想要操纵文件的内容,则他/她必须使用流,而不管数据量如何。对于网络流也同样如此。诚然,如果程序员正在使用像C这样的低级语言进行编码,则可以将char或字节直接写入磁盘或套接字,但是即使是少量数据,也很耗时并且更容易错误。
1c1cle

10

流只是physical字节流的抽象(或包装)。此physical流称为base stream。所以总是有在其上流封包被创建并基本流类型之后即由此所述包装被命名为基本流FileStreamMemoryStream

流包装器的优点是您可以获得一个统一的api,可与任何基础类型usb, file等的流进行交互。

为什么将数据视为流 -因为数据块是按需加载的,所以我们可以将数据作为块检查/处理,而不是将整个数据加载到内存中。这就是大多数程序处理大文件的方式,例如,加密OS映像文件。


4

仅有一种基本类型Stream。但是,在各种情况下,某些成员在被调用时将引发异常,因为在这种情况下该操作不可用。

例如,a MemoryStream只是一种将字节移入和移出内存块的方法。因此,您可以对其调用读和写。

另一方面,a FileStream允许您从文件读取或写入文件(或两者)。您是否可以实际读取或写入取决于打开文件的方式。如果仅以读取访问权限打开文件,则无法写入文件。


3

我将从阅读MSDN上的流开始:http : //msdn.microsoft.com/zh-cn/library/system.io.stream.aspx

Memorystream和FileStream是分别用于处理原始内存和文件的流...


感谢您的链接。我喜欢“您可以在线浏览源代码,下载参考以供离线查看,并在调试过程中逐步浏览源代码(包括补丁和更新)”。此功能提供了新的见解水平。
大卫,

1

我不会叫那些不同类型的流。Stream类具有CanRead和CanWrite属性,它们告诉您是否可以读取和写入特定的流。

不同流类(例如MemoryStream和FileStream)之间的主要区别是后备存储-从中读取数据或将数据写入其中。从名称上可以明显看出。MemoryStream仅将数据存储在内存中,FileStream由磁盘上的文件支持,NetworkStream从网络读取数据,依此类推。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.