正如前面所述,Java的字节流既功能强大,又十分灵活.然而他们并不是处理字符IO的理想途径.为此,Java定义了字符流类.在字符流层次结构的顶端是抽象类Reader和Writer.下表,列出了Reader类的方法,所有的方法出现错误时都抛出IOException.由这两个抽象类定义的方法对于所有子类都是有效的.因此,他们就形成了一个所有字符流都应具备的最小IO功能集合.
方法
|
描述
|
abstract void close()
|
关闭输入源,而且任何读操作都会产生IOException
|
void mark(int numChars)
|
在输入流的当前点放置标记,标记在读取numChars个字符之前一直保持有效
|
int read()
|
返回一个整数,表示调用输入流的下一个有效字符.当到达文件末尾时返回-1
|
int read(char buffer[])
|
尝试读取buffer length个字符到缓冲区,并返回读取的实际字符数.当到达文件末尾时,返回-1
|
abstract int read(char buffer[],int offsize,int numChars)
|
尝试读取numChars个字符到缓冲区中以buffer[offsize]开始的位置,返回成功读取的字符数.当到达文件末尾时,返回-1
|
int read(CharBuffer buffer)
|
尝试填充buffer指定的缓冲区,返回成功读取的字符数.当到达文件末尾时返回-1.charBuffer是一个封装字符序列的类
|
boolean ready()
|
如果下一个输入请求不等待就返回true,否则返回false
|
void reset() |
将输入指针重置为前面设定的标记
|
long skip(long numChars)
|
跳过输入的numChars个字符,返回实际跳过的字符数
|
下表列出了writer类的方法:
方法
|
描述 |
write append(char ch)
|
把ch追加到调用输出流的末尾,返回调用输出流的引用
|
write append(charSequence char)
|
把char追加到调用输出流的末尾,返回调用输出流的引用,charSequence是一个定义字符序列上的制度操作的接口
|
write append(CharSequence chars,int begin,int end)
|
把chars的从begin到end之间的字符序列追加到调用输出流的末尾,返回调用输出流的引用.CharSequence是一个定义字符序列上的制度操作接口
|
abstract void close()
|
关闭输出流,而且任何写操作都会产生IOException
|
abstract void flush()
|
将已经缓冲的任何输出发送到其目标,即他用于刷新输出缓冲区
|
void write(int ch)
|
向调用输出流写入一个字符,注意形参是int类型,他支持直接用表达式调用write()而无须将他们强制转换为char
|
void write(char buffer[])
|
向调用输出流写入一个完整的字符数组
|
abstract void write(char buffer[],int offset,int numChars)
|
从数组缓冲区的buffer[offset]开始向输出流写入numChars个字符的子区间
|
void write(string str)
|
向调用输出流写入str
|
void write(string str,int offset,int numChars)
|
从指定的offset开始,从数组str写入numChars个字符的子区间
|
1.使用字符流的控制台输入
对于要国际化的代码而言,使用Java字符流从控制台输入作为一种键盘读取字符的方法比使用字节流更好,更方便.然而,因为System.in是一个字节流,所以需要将System.in包含在某一类型的Reader中.读取控制台输入最合适的类是BufferReader,他支持缓冲的输入流.然而,不能直接从System.in构造BufferedReader.必须首先将他转换为一个字符流.为此,需要使用InputStreamReader把字节转换为字符.为获得与System.in链接的InputStream-Reader对象,需要使用下面所示的构造函数:
InputStreamReader(InputStream inputStream)
因为System.in引用一个InputStream类型的对象,所以他可以用于inputStream.
接下来,使用InputStreamReader产生的对象,使用下面的构造函数构造一个BufferedReader,如下所示:
BufferReader(Reader inputReader)
这里,inputReader是与创建的BufferedReader实例链接的流,把他放在一起,下面的代码行创建了与键盘相连的BufferReader:
bufferedReader br = new bufferedReader(new inputStreamReader(System.in))
这条语句执行之后,br将称为一个通过System.in与控制台相连的字符流
(1)读取字符
使用BufferedReader定义的read()方法从System.in读取字符与使用字节流读取十分相似.BufferedReader定义了下面这三个版本的read()
int read() throws IOException int read(char data[]) throws IOException int read(char data[],int start,int max) throws IOException
第一个read()读取一个Unicode字符.当到达流的末尾时,返回-1.第二个read()从输入流读取字符,然后把他们放入data直到数组满,到达文件末尾或发生错误为止.他返回读取的字符的数量,或者在到达流的末尾时返回-1.第三个read()从start指定的位置开始读取输入到data,直到存储了max个字符为止.他返回读取字符的数量,或在在到达流的末尾时返回-1.这三个read()版本在发生错误时都抛出IOException,当从System.in读取时,按Enter键可以产生一个流结束的条件.
下面的程序通过从控制台读取字符直到用户输入一个句点为止演示了read()的用法,注意任何可能生成的IO异常都只是抛出到main()之外,在从控制台读取字符时这种方法是通用的,当然,也可以选择在程序控制下处理这些类型的错误.
public static void main(String args[]) throws IOException { char c; BufferedReader br = new BufferedReader( new InputStreamReader(System.in) ); do { c = (char) br.read(); System.out.println(c); } while(c!='.'); }
运行结果:
dsdsad d s d s a d
(2)读取字符串
为从键盘读取字符串,需要使用BufferedReader类成员readLine(),其基本形式如下所示:
String readLine() throws IOException
他返回的String对象包含了读取的字符.如果试图在流的末尾读取,就会返回null.下面的程序演示了BufferedReader类和readLine()方法,程序读取并显示文本行,直到输入单词stop
public static void main(String args[]) throws IOException { String c; BufferedReader br = new BufferedReader( new InputStreamReader(System.in) ); do { c = br.readLine(); System.out.println(c); } while(!c.equals("stop")); System.out.println("exit"); }
2.使用字符流的控制台输出
尽管Java还允许使用System.out向控制台写入,但是他更多的应用于调试程序或如本书出现的那样用于示例程序.对于真正的程序而言,在Java中向控制台写入的更合适的方法是使用printWrite流.PrintWrite是一个字符流类.如上所言,使用字符类进行控制台输出可使程序的国际化更为简单.
printWriter定义了几个构造函数,我们将使用的构造函数如下所示:
printWriter(outputStream ,boolean flushingOn)
这里,outputStream是一个outputStream类型的对象,,而flushOnNewLine控制Java是否在每次调用println()方法时刷新输出流.如果flushOnNewLine为true,刷新就会自动进行.如果为false,刷新就不是自动进行的.
printWriter支持包括Object在内的所有类型的print()和println()方法.因此,可以像在System.out中使用他们一样使用这些方法.如果实参不是基本类型,printWriter方法将调用对象的toString()方法,然后打印结果.
为了使用printWriter向控制台写入,需要为输出流指定System.out,在每一次调用println()之后刷新流.例如,下面这行代码创建了一个与控制台输出相连的printWriter:
printWriter pw = new printWriter(System.out,true);
下面的应用程序演示了如何使用printWriter来处理控制台输出:
public static void main(String args[]) throws IOException { PrintWriter pw = new PrintWriter(System.out,true); int i=10; double d = 123.33; pw.println("Using a PrintWriter."); pw.println(i); pw.println(d); }
输出:
Using a PrintWriter. 10 123.33
切记,当在学习Java或调用程序时使用System.out向控制台输出简单的文本是没有错的.然而,使用printWriter会使实际的应用程序更易于国际化.