流、文件及基于文本的应用
1、流式输入与输出
为进行数据的输入、输出操作,Java中把不同的输入、输出源(键盘、文件、网络连接等)抽象为“流”(Stream),有两种基本的流:输入流和输出流。
(1)输入流:只能从中读取数据,而不能向其写出数据。
(2)输出流:只能向其写出数据,而不能从中读取数据。
流实际上指在计算机的输入与输出之间运动的数据的序列,流序列中的数据既可以是未经加工的原始二进制数据,也可以是经一定编码处理后符合某种格式规定的特定数据,如字符流序列、数字流序列等。
1.1、字节流与字符流
按处理数据的类型,流可以分为字节流和字符流,它们处理的信息的基本单位分别是字节(byte)与字符(char)。
输入字节流的类为InputStream
输出字节流的类为OutputStream
输入字符流的类为Reader
输出字符流的类为Writer
如下表,这四个类是抽象类,其他的输入输出流类都是它们的子类。
字节流与字符流
|
字节流
|
字符流
|
输入
|
InputStream
|
Reader
|
输出
|
OutputStream
|
Writer
|
InputStream类
方法摘要 |
int |
available() 返回此输入流方法的下一个调用方可以不受阻塞地从此输入流读取(或跳过)的字节数。 |
void |
close() 关闭此输入流并释放与该流关联的所有系统资源。 |
void |
mark(int readlimit) 在此输入流中标记当前的位置。 |
boolean |
markSupported() 测试此输入流是否支持 mark 和 reset 方法。 |
abstract int |
read() 从输入流读取下一个数据字节。 |
int |
read(byte[] b) 从输入流中读取一定数量的字节并将其存储在缓冲区数组 b 中,以整数形式返回实际读取的字节数。 |
int |
read(byte[] b, int off, int len) 将输入流中最多 len 个数据字节读入字节数组,将读取的第一个字节存储在元素 b[off] 中,下一个存储在 b[off+1] 中,依次类推。读取的字节数最多等于 len 。 |
void |
reset() 将此流重新定位到对此输入流最后调用 mark 方法时的位置。 |
long |
skip(long n) 跳过和放弃此输入流中的 n 个数据字节。 |
第一个read()方法从输入流的当前位置处读入一个字节(8位)的二进制数据,然后以此数据为低位字节,配上一个全零字节合成为一个16位的整型量(0~255)后返回给调用此方法的语句。如果输入流的当前位置没有数据,则返回-1。
OutputStream类
此抽象类是表示输出字节流的所有类的超类。输出流接受输出字节并将这些字节发送到某个接收器。
方法摘要 |
void |
close() 关闭此输出流并释放与此流有关的所有系统资源。 |
void |
flush() 刷新此输出流并强制写出所有缓冲的输出字节。 |
void |
write(byte[] b) 将 b.length 个字节从指定的字节数组写入此输出流。 |
void |
write(byte[] b, int off, int len) 将指定字节数组中从偏移量 off 开始的 len 个字节写入此输出流。 |
abstract void |
write(int b) 将指定的字节写入此输出流。 |
public abstract void write(int b) throws
IOException将指定的字节写入此输出流。write 的常规协定是:向输出流写入一个字节。要写入的字节是参数 b 的八个低位。b 的 24 个高位将被忽略。 OutputStream 的子类必须提供此方法的实现。
flush()方法刷新缓冲区的内容。对于缓冲流式输出来说,write()方法所写的数据并没有直接传到与输出流相连的外部设备上,而是先暂时存放在流的缓冲区中,等到缓冲区中的数据积累到一定数量,再统一执行一次向外部设备的写操作把它们全部写到外部设备上。这样处理可以降低计算机对外部设备的读写次数,大大提高系统的效率。但是在某些情况下,缓冲区中的数据不满时就需要将它写到外部设备上,此时应使用强制清空缓冲区并执行外部设备写操作的flush()方法。
Reader类
Reader类与InputStream类相似,都是输入流,但差别在于Reader类读入的是字符(char),而不是字节。
方法摘要 |
abstract void |
close() 关闭该流。 |
void |
mark(int readAheadLimit) 标记流中的当前位置。 |
boolean |
markSupported() 判断此流是否支持 mark() 操作。 |
int |
read() 读取单个字符。 |
int |
read(char[] cbuf) 将字符读入数组。 |
abstract int |
read(char[] cbuf, int off, int len) 将字符读入数组的某一部分。 |
int |
read(CharBuffer target) 试图将字符读入指定的字符缓冲区。 |
boolean |
ready() 判断是否准备读取此流。 |
void |
reset() 重置该流。 |
long |
skip(long n) 跳过字符。 |
Writer 类
1、2节点流和处理流按照流是否直接与特定的地方(如磁盘、内存、设备等)相连,分为节点流与处理流两类。
(1)节点流(Node Stream):可以从或向一个特定的地方(节点)读写数据。如文件流FileReader
(2)处理流(Processing Stream):是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写功能。处理流又称为过滤流,如缓冲处理流BufferReader。
节点流与处理流的关系:节点流直接与节点(如文件)相连,而处理流对节点流或其他处理流进一步进行处理(如缓冲、组装成对象,等等)。
处理流的构造方法总是要带一个其他流对象作为参数。 如:
BufferedReader iin = new BufferedReader(new FileReader(file));
常用的节点流:
节点类型 |
节点流 |
字符流 |
File文件 |
FileInputStream
FileOutputStream
|
FileReader
FileWriter
|
Memory Array内存数组 |
ByteArrayInputStream
ByteArrayOutputStream
|
CharArrayReader
CharArrayWriter
|
Memory String字符串 |
|
StringReader
StringWriter
|
Pipe管道 |
PipedInputStream
PipedOutputStream
|
PipedReader
PipedWriter
|
常用的处理流
处理类型 |
字节流 |
字符流 |
Buffering缓冲 |
BufferedInputStream
BufferedOutputStream
|
BufferedReader
BufferedWriter
|
Filtering过滤 |
FilterInputStream
FilterOutputStream
|
FilterReader
FilterWirter
|
Converting between bytes and character
字节流转为字符流
|
|
InputStreamReader
OutputStreamWriter
|
Object Serialization
对象序列化
|
ObjectInputStream
ObjectOutputStream
|
|
Date coversion
基本数据类型转化
|
DateInputStream
DateOutputStream
|
|
Counting行号处理
|
LineNumberInputStream |
LineNumberReader |
Peeking ahead可回退流
|
PushBackInputStream |
PushbackReader |
Pinting可显示处理 |
PrintStream |
PrintWriter |
基本输入、输出流是定义基本的输入、输出操作的抽象类,在Java程序中真正实用的是它们的子类,对应于不同的数据源和输入、输出任务,以及不同的输入、输出流。其中较常用的有:过滤输入、输出流FilterInputStream和FilterOutputStream两个抽象类,又分别派生出DataInputStream,DataOutputStream等子类。过滤输入、输出流的主要特点是在输入、输出数据的同时能对所传输的数据做指定类型或格式的转换,即可实现对二进制字节数据的理解和编码转换。文件输入、输出流FileInputStream和FileOutputStream主要负责完成对本地磁盘文件的顺序读写操作。管道输入、输出流PipedInputStream和PipedOutputStream负责实现程序内部的线程间通信或不同程序间通信。字节数组流ByteArrayInputStream和ByteArrayOutputStream可实现与内存缓冲区的同步读写。顺序输入流SequenceInputStream可以把两个其他的输入流首尾相接,合并成一个完整的输入流,等等。
从抽象类Reader和Writer中也派生出一些子类,这些子类使InputStream和OutputStream的以字节为单位输入、输出转换为以字符为单位输入、输出,使用起来比InputStream和OutputStream要方便很多。
数据输入、输出流DataInputStream和DataOutputStream分别是过滤输入、输出流FilterInputStream和FilterOutputStream的子类。过滤输入、输出流的最主要作用就是在数据源和程序之间加一个过滤处理步骤,对原始数据做特定的加工、处理和变换操作。
标准输入和标准输出 当java程序需要与外界数据源做输入、输出的数据交换时,它需要首先创建一个输入或输出类的对象来完成对这个数据源的连接。例如,当java程序需要读写文件时,它需要先创建文件的输入或文件输出流类的对象。除文件外,程序也经常使用字符界面的标准输入、输出设备进行读写操作。
计算机系统都有默认的标准输入设备和标准输出设备。对一般的系统,标准输入通常是键盘,标准输出通常是显示器屏幕。Java程序使用字符界面与系统标准输入、输出间进行数据通信,即从键盘读入数据,或向屏幕输出数据,是十分常见的操作,为此而频频创建输入、输出流类对象将很不方便。为此java系统事先定义好两个流对象,分别与系统的标准输入和标准输出相联系,它们是System.in和System.out