第 15 章 文件和流 文件和流
本作品已使用人工智能进行翻译。欢迎您提供反馈和意见:translation-feedback@oreilly.com
到目前为止,我在本书中展示的大部分技术都是围绕对象和变量中的信息展开的。这种状态存储在特定进程的内存中,但要发挥作用,程序必须与更广阔的世界进行交互。这可以通过用户界面框架来实现,但有一种特殊的抽象可以用于与外部世界的多种交互:流。
流在计算机中的应用非常广泛,毫无疑问,您对它已经非常熟悉了。.NET 流与大多数其他编程系统中的流基本相同:它只是一个字节序列。这使得流成为许多常见功能的有用抽象,如磁盘上的文件或 HTTP 响应的正文。控制台应用程序使用流来表示其输入和输出。如果以交互方式运行这样的程序,用户在键盘上输入的文本就会成为程序的输入流,而程序写入输出流的任何内容都会显示在屏幕上。不过,程序并不一定知道它的输入或输出是什么类型的--你可以通过控制台程序重定向这些流。例如,输入流可能是磁盘上的文件内容,也可能是其他程序的输出。
备注
并非所有 I/O API 都是基于流的。例如,除了输入流外,Console 类还提供了一个ReadKey 方法,该方法可提供按下哪个键的确切信息,但只有当输入来自键盘时,该方法才会起作用。因此,虽然你可以编写不关心输入是来自交互式输入还是文件输入的程序,但有些程序还是比较挑剔的。
流应用程序接口提供的是原始字节数据。不过,也可以在不同的层次上工作。例如,有一些面向文本的 API 可以封装底层流,因此您可以处理字符或字符串,而不是原始字节。此外,还有各种序列化机制,可以将 .NET 对象转换为流表示,之后再将其转换为对象,这样就可以持久保存对象的状态,或通过 Network+ 发送该状态。稍后我将介绍这些更高级别的 API,但首先让我们来看看流抽象本身。
溪流类
Stream 类定义在 命名空间中。它是一个抽象基类,具体派生类型(如 或 )代表特定类型的流。System.IO FileStream GZipStream 例 15-1显示了 类最重要的三个成员。它还有其他几个成员,但这些是抽象的核心。(稍后您将看到, 和 也有异步版本。.NET Core 3.1 和 .NET 还提供了重载,可以使用Stream Read Write第 18 章中描述的跨类型之一来代替数组。 本节中有关这些方法的所有内容也适用于异步和基于 span 的形式(参见第 18 章)。
例 15-1. 最重要的成员Stream
publicabstractintRead(byte[]buffer,intoffset,intcount);publicabstractvoidWrite(byte[]buffer,intoffset,intcount);publicabstractlongPosition{get;set;}
有些数据流是只读的。例如,当控制台应用程序的输入流代表键盘或其他程序的输出时,程序就无法向该输入流写入任何内容。(为了保持一致性,即使使用输入重定向来运行以文件为输入的控制台程序,输入流也将是只读的)。有些流是只写的,例如控制台应用程序的输出流。如果在只写数据流上调用Read 或在只读数据流上调用Write ,这些方法都会抛出NotSupportedException 。
提示
Stream 类定义了各种bool 属性,用于描述数据流的功能,因此不必等到出现异常时才知道数据流的类型。您可以查看CanRead 或CanWrite ...
Become an O’Reilly member and get unlimited access to this title plus top books and audiobooks from O’Reilly and nearly 200 top publishers, thousands of courses curated by job role, 150+ live events each month,
and much more.
Read now
Unlock full access