输入和输出术语有时会让人感到困惑。应用程序一部分的输入往往是另一部分的输出。OutputStream 是输出写入流,还是输出输出(供你读取)流?毕竟,InputStream 会将数据输出给读取程序,不是吗?就我个人而言,在我刚开始学习 Java IO 的时候,我觉得这有点令人困惑。
为了消除这种可能的混淆,我尝试给输入和输出起了一些不同的名字,试图从概念上将它们与输入的来源和输出的去向联系起来。
Java 的 IO 包主要涉及从数据源读取原始数据和向目的地写入原始数据。最典型的数据源和目的地有以下几种:
文件
管道
网络连接
内存缓冲区(例如数组)
System.in(标准输入)、System.out(标准输出)、System.error(标准错误输出)
下图说明了程序从数据源读取数据并将其写入某个目的地的原理:
IO 流是 Java IO 的核心概念。从概念上讲,数据流是无穷无尽的数据流。您可以从数据流中读取数据,也可以向数据流中写入数据。数据流与数据源或数据目标相连。Java IO 中的流可以是基于字节的(读写字节),也可以是基于字符的(读写字符)。
需要从某个源读取数据的程序需要一个 InputStream 或 Reader。需要向某个目的地写入数据的程序需要一个 OutputStream 或 Writer。如下图:
上图中,一个输入流(InputStream)或读取器(Reader)与数据源相连。一个输出流(OutputStream)或写入器(Writer)与数据目的地相连。
Java IO(Input/Output)即 Java 的输入输出系统,是 Java 编程中用于处理数据传输的重要部分,它提供了一系列类和接口,让程序能够与各种数据源(如文件、网络连接、内存缓冲区等)进行数据的读取和写入操作。实际开发中,大多数应用程序都需要处理一些输入,并根据这些输入产生一些输出。例如,从文件或通过网络读取数据,然后写入文件或通过网络写回响应。
示例:读取一个文件到内容,并将内容在控制台打印。
package com.hxstrive.java_io; import java.io.FileInputStream; /** * 读取文件示例 * @author hxstrive.com */ public class HelloWorld { public static void main(String[] args) { // 读取文件内容 try(FileInputStream fileInputStream = new FileInputStream("D:\\input.txt")) { byte[] bytes = new byte[fileInputStream.available()]; int len = fileInputStream.read(bytes); System.out.println(len); // 13 System.out.println(new String(bytes)); // Hello Java IO } catch (Exception e) { e.printStackTrace(); } } }
运行结果:
13 Hello Java IO
实际上,java.io 包并不涉及所有类型的输入和输出。例如,来自图形用户界面或网页的输入和输出就不在 Java IO 包的覆盖范围内。这些类型的输入都包含在其他地方,例如 Swing 项目中的 JFC 类,或 Java 企业版中的 Servlet 和 HTTP 包。
Java IO 包主要侧重于文件、网络流、内部内存缓冲区等的输入和输出。但是,Java IO 包不包含打开网络通信所需的网络套接字的类。为此,您需要使用 Java 网络 API。一旦打开了套接字(网络连接),您就可以通过 Java IO 的 InputStream 和 OutputStream 类读写数据。
JavaDoc 是 Java 自带的一种工具,它能够从 Java 源代码文件里提取特定格式的注释信息,然后自动生成 HTML 格式的 API 文档。这些文档详细描述了类、接口、方法、字段等的用途、使用方式和注意事项,对于代码的理解、维护以及开发者之间的协作都有很大帮助。
为了更好到学习 Java IO,我们需要时刻参考 API 文档,地址:
https://docs.oracle.com/javase/8/docs/api/overview-summary.html
注意:Java IO 的 API 位于 java.io 包,如果您查看 java.io 包的 javadoc 文档,你会发现 java.io 包中存在大量的类/接口/枚举, 也就意味着你有大量的选择,这可能会让您感到相当困惑,不知道如何开始。
JavaDoc 文档如下图:
上图中,所有这些类的目的是什么?应该选择哪个类来完成特定任务?教程将在后续章节详细介绍。
Java IO 包含 InputStream、OutputStream、Reader 和 Writer 接口的许多子类,这些子类都是为了实现各种不同的目的。这就是为什么有这么多不同的类,下面总结了这些目的:
文件访问
网络访问
内部内存缓冲区访问
线程间通信(管道)
缓冲
过滤
解析
读写文本(读取器/写入器)
读写原始数据(long、int 等)
读写对象
注意:在阅读 Java IO 类时,了解这些目的很有帮助,它使我们更容易理解这些类的目标。
在讨论了来源、目的地、输入、输出以及 Java IO 类所针对的各种 IO 目的之后,下面的表格列出了大多数(如果不是全部)Java IO 类,它们按输入、输出、基于字节还是基于字符,以及它们可能针对的更具体的目的(如缓冲、解析等)进行了划分。
基于字节 | 基于字符 | |||
Input(输入) | Output(输出) | Input(输入) | Output(输出) | |
基础 | InputStream | OutputStream | Reader | Writer |
数组 | ByteArrayInputStream | ByteArrayOutputStream | CharArrayReader | CharArrayWriter |
文件 | FileInputStream | FileOutputStream | FileReader | FileWriter |
管道 | PipedInputStream | PipedOutputStream | PipedReader | PipedWriter |
缓冲 | BufferedInputStream | BufferedOutputStream | BufferedReader | BufferedWriter |
过滤 | FilterInputStream | FilterOutputStream | FilterReader | FilterWriter |
解析 | PushbackInputStream | PushbackReader | ||
字符串 | StringReader | StringWriter | ||
数据 | DataInputStream | DataOutputStream | ||
数据 - 已格式化 | PrintStream | PrintWriter | ||
对象 | ObjectInputStream | ObjectOutputStream | ||
实用工具 | SequenceInputStream |
Java NIO(New Input/Output)是从 Java 1.4 版本开始引入的一套新的 I/O API,它为 Java 开发者提供了与标准 Java I/O 不同的处理方式,旨在提高 I/O 操作的效率,特别是在处理高并发网络应用和大量数据传输时表现出色。下面将从核心组件、工作原理、与传统 IO 的对比、示例代码等方面详细介绍 Java NIO。
注意,本教程将不会介绍涉及 Java NIO 到知识,将额外提供教程介绍。