Java程序通过流来完成输入/输出。流是生产或消费信息的抽象。流通过Java的输入/输出系统与物理设备链接。尽管与它们链接的物理设备不尽相同,所有流的行为具有同样的方式。这样,相同的输入/输出类和方法适用于所有类型的外部设备。
这意味着一个输入流能够抽象多种不同类型的输入:从磁盘文件,从键盘或从网络套接字。同样,一个输出流可以输出到控制台,磁盘文件或相连的网络。流是处理输入/输出的一个洁净的方法,例如它不需要代码理解键盘和网络的不同。Java中流的实现是在java.io包定义的类层次结构内部的。
字节流和字符流
字节流为处理字节的输入和输出提供了方便的方法。例如使用字节流读取或书写二进制数据。字符流为字符的输入和输出处理提供了方便。它们采用了统一的编码标准,因而可以国际化。当然,在某些场合,字符流比字节流更有效。
Java的原始版本(Java 1.0)不包括字符流,因此所有的输入和输出都是以字节为单位的。Java 1.1中加入了字符流,某些字节形式的类和方法不受欢迎。这也是为什么没用字符流的老代码在适当的地方需要更新的原因。
需要声明:在最底层,所有的输入/输出都是字节形式的。基于字符的流只为处理字符提供方便有效的方法。
下面是对字节流和字符流的概述。
字节流类 字节流由两个类层次结构定义。在顶层有两个抽象类:InputStream 和 OutputStream。每个抽象类都有多个具体的子类,这些子类对不同的外设进行处理,例如磁盘文件,网络连接,甚至是内存缓冲区。字节流类显示于表中。
| 流类 | 含义 |
|---|---|
| BufferedInputStream | 缓冲输入流 |
| BufferedOutputStream | 缓冲输出流 |
| ByteArrayInputStream | 从字节数组读取的输入流 |
| ByteArrayOutputStream | 向字节数组写入的输出流 |
| DataInputStream | 包含读取Java标准数据类型方法的输入流 |
| DataOutputStream | 包含编写Java 标准数据类型方法的输出流 |
| FileInputStream | 读取文件的输入流 |
| FileOutputStream | 写文件的输出流 |
| FilterInputStream | 实现 InputStream |
| FilterOutputStream | 实现 OutputStream |
| InputStream | 描述流输入的抽象类 |
| OutputStream | 描述流输出的抽象类 |
| PipedInputStream | 输入管道 |
| PipedOutputStream | 输出管道 |
| PrintStream | 包含print( ) 和 println( )的输出流 |
| PushbackInputStream | 支持向输入流返回一个字节的单字节的“unget”的输入流 |
| RandomAccessFile | 支持随机文件输入/输出 |
| SequenceInputStream | 两个或两个以上顺序读取的输入流组成的输入流 |
抽象类InputStream 和 OutputStream定义了实现其他流类的关键方法。最重要的两种方法是read()和write(),它们分别对数据的字节进行读写。两种方法都在InputStream 和OutputStream中被定义为抽象方法。它们被派生的流类重载。
字符流类 字符流类由两个类层次结构定义。顶层有两个抽象类:Reader和Writer。这些抽象类处理统一编码的字符流。Java中这些类含有多个具体的子类。
字符流的输入/输出类
| 流类 | 含义 |
|---|---|
| BufferedReader | 缓冲输入字符流 |
| BufferedWriter | 缓冲输出字符流 |
| CharArrayReader | 从字符数组读取数据的输入流 |
| CharArrayWriter | 向字符数组写数据的输出流 |
| FileReader | 读取文件的输入流 |
| FileWriter | 写文件的输出流 |
| FilterReader | 过滤读 |
| FilterWriter | 过滤写 |
| InputStreamReader | 把字节转换成字符的输入流 |
| LineNumberReader | 计算行数的输入流 |
| OutputStreamWriter | 把字符转换成字节的输出流 |
| PipedReader | 输入管道 |
| PipedWriter | 输出管道 |
| PrintWriter | 包含print( )和println( )的输出流 |
| PushbackReader | 允许字符返回到输入流的输入流 |
| Readerr | 描述字符流输入的抽象类 |
| StringReader | 读取字符串的输入流 |
| StringWriter | 写字符串的输出流 |
| Writer | 描述字符流输出的抽象类 |
抽象类Reader和Writer定义了几个实现其他流类的关键方法。其中两个最重要的是read()和write(),它们分别进行字符数据的读和写。这些方法被派生流类重载。
预定义流 所有的Java程序自动导入java.lang包。该包定义了一个名为System的类,该类封装了运行时环境的多个方面。例如,使用它的某些方法,你能获得当前时间和与系统有关的不同属性。
System 同时包含三个预定义的流变量,in,out和err。这些成员在System中是被定义成public 和static型的,这意味着它们可以不引用特定的System对象而被用于程序的其他部分。
System.out是标准的输出流。默认情况下,它是一个控制台。
System.in是标准输入,默认情况下,它指的是键盘。System.err指的是标准错误流,它默认是控制台。然而,这些流可以重定向到任何兼容的输入/输出设备。
System.in是inputStream的对象;System.out和System.err是PrintStream的对象。它们都是字节流,尽管它们用来读写外设的字符。如果愿意,你可以用基于字符的流来包装它们。
你可以以同样的方式使用System.err。下面对此进行解释,你会看到使用System.in有一点复杂。