17.4.9 SequenceInputStream(顺序输入流)
SequenceInputStream类允许连接多个InputStream流。SequenceInputStream的构造不同于任何其他的InputStream。SequenceInputStream构造函数要么使用一对InputStream,要么用InputStream的一个Enumeration,显示如下:
SequenceInputStream(InputStream first, InputStream second)
SequenceInputStream(Enumeration streamEnum)
操作上来说,该类满足读取完第一个InputStream后转去读取第二个流的读取要求。使用Enumeration的情况下,它将继续读取所有InputStream流直到最后一个被读完。
下面是用SequenceInputStream输出两个文件内容的例子程序:
// Demonstrate sequenced input.
import java.io.*;
import java.util.*;
class InputStreamEnumerator implements Enumeration {
private Enumeration files;
public InputStreamEnumerator(Vector files) {
this.files = files.elements();
}
public boolean hasMoreElements() {
return files.hasMoreElements();
}
public Object nextElement() {
try {
return new FileInputStream(files.nextElement().toString());
} catch (Exception e) {
return null;
}
}
}
class SequenceInputStreamDemo {
public static void main(String args[]) throws Exception {
int c;
Vector files = new Vector();
files.addElement("/autoexec.bat");
files.addElement("/config.sys");
InputStreamEnumerator e = new InputStreamEnumerator(files);
InputStream input = new SequenceInputStream(e);
while ((c = input.read()) != -1) {
System.out.print((char) c);
}
input.close();
}
}
该例创建了一个Vector 向量并向它添加了两个文件名。它把名字向量传给InputStreamEnumerator类,设计该类是为了提供向量包装器,向量返回的元素不是文件名,而是用这些名称打开FileInputStream流。SequenceInputStream依次打开每个文件,该程序打印了两个文件的内容。
17.4.10 PrintStream(打印流)
PrintStream具有本书开始以来我们在System文件句柄使用过的System.out所有的格式化性能。PrintStream有两个构造函数:
PrintStream(OutputStream outputStream)
PrintStream(OutputStream outputStream, boolean flushOnNewline)
当flushOnNewline 控制Java 每次刷新输出流时,输出一个换行符( \n )。如果flushOnNewline为true,自动刷新。若为false,刷新不能自动进行。第一个构造函数不支持自动刷新。Java的PrintStream对象支持包括Object在内的各种类型的 print( ) 和 println( )方法。如果参数不是一个简单类型,PrintStream方法将调用对象的 toString( ) 方法,然后打印结果。
17.4.11 RandomAccessFile(随机访问文件类)
RandomAccessFile 包装了一个随机访问的文件。它不是派生于InputStream 和OutputStream,而是实现定义了基本输入/输出方法的DataInput和DataOutput接口。它同样支持定位请求——也就是说,可以在文件内部放置文件指针。它有两个构造函数:
RandomAccessFile(File fileObj, String access)
throws FileNotFoundException
RandomAccessFile(String filename, String access)
throws FileNotFoundException
第一种形式,fileObj指定了作为File 对象打开的文件的名称。第二种形式,文件名是由filename参数传入的。两种情况下,access 都决定允许访问何种文件类型。如果是“r”,那么文件可读不可写,如果是“rw”,文件以读写模式打开。下面所示的seek( )方法,用来设置文件内部文件指针的当前位置:
void seek(long newPos) throws IOException
这里,newPos 指文件指针从文件开始以字节方式指定新位置。调用seek( )方法后,接下来的读或写操作将在文件的新位置发生。RandomAccessFile 实现了用来读写随机访问文件的标准的输入和输出方法。下面是Java 2增添的新方法setLength( )。它有下面的形式:
void setLength(long len) throws IOException
该方法通过指定的len设置正在调用的文件的长度。该方法可以增长或缩短一个文件。如果文件被加长,增加的部分是未定义的。
17.5 字 符 流
尽管字节流提供了处理任何类型输入/输出操作的足够的功能,它们不能直接操作Unicode字符。既然Java的一个主要目的是支持“只写一次,到处运行”的哲学,包括直接的字符输入/输出支持是必要的。本节将讨论几个字符输入/输出类。如前所述,字符流层次结构的顶层是Reader 和Writer 抽象类。我们将从它们开始。
注意:如第12章讨论过的,字符输入/输出类是在java 的1.1版本中新加的。由此,你仍然可以发现遗留下的程序代码在应该使用字符流时却使用了字节流。当遇到这种代码,最好更新它。
17.5.1 Reader
Reader是定义Java的流式字符输入模式的抽象类。该类的所有方法在出错情况下都将引发IOException 异常。表17-3给出了Reader类中的方法。
表17-3 Reader 定义的方法
方法 描述
abstract void close( ) 关闭输入源。进一步的读取将会产生IOException异常
void mark(int numChars) 在输入流的当前位置设立一个标志。该输入流在numChars个字符被读取之前有效
boolean markSupported( ) 该流支持mark( )/reset( )则返回true
int read( ) 如果调用的输入流的下一个字符可读则返回一个整型。遇到文件尾时返回-1
int read(char buffer[ ]) 试图读取buffer中的buffer.length个字符,返回实际成功读取的字符数。遇到文件尾返回-1
abstract int read(char buffer[ ],int offset,
int numChars)
试图读取buffer中从buffer[offset]开始的numChars个字符,
返回实际成功读取的字符数。遇到文件尾返回-1
boolean ready( ) 如果下一个输入请求不等待则返回true,否则返回false
void reset( ) 设置输入指针到先前设立的标志处
long skip(long numChars) 跳过numChars个输入字符,返回跳过的字符数
17.5.2 Writer
Writer 是定义流式字符输出的抽象类。所有该类的方法都返回一个void 值并在出错条件下引发IOException 异常。表17-4 给出了Writer类中方法。
表17-4 Writer 定义的方法
方法 描述
abstract void close( ) 关闭输出流。关闭后的写操作会产生IOException异常
abstract void flush( ) 定制输出状态以使每个缓冲器都被清除。也就是刷新输出缓冲
void write(int ch) 向输出流写入单个字符。注意参数是一个整型,它允许你不必把参数转换成字符型就可以调用write()
void write(char buffer[ ]) 向一个输出流写一个完整的字符数组
续表
方法 描述
abstract void write(char buffer[ ],
int offset,int numChars)
向调用的输出流写入数组buffer 以buffer[offset] 为起点的
numChars个字符区域内的内容
void write(String str) 向调用的输出流写str
void write(String str, int offset,
int numChars)