推回输入流
在Java输入、输出流体系中有两个特殊的流与众不同,就是PushbackInputStream/PashbackReader,它们都提供了如下三个方法:
?void unread(byte[]/char[] buf):将以一个字节/字符数组内容推回到推回缓冲区里,从而允许重复读取刚刚读取的内容。
?void unread(byte[] /char[] buf, int off,int ben):把一个字节/字符数组从off开始,长度为len字节/字符的内容推回到推回缓冲区里,从而允许重复读取刚刚读取的内容
?void unread(int b):将一个字节/字符推回到推回缓冲区里,从而允许重复读取刚刚读取的内容
这两个输入了都带有一个推回缓冲区,当成程序调用者两个推回输入流的unread方法时,系统将会把指定数组里的内容推回到该缓冲区里,而推回输入流每次调用read方法时总是先从推回缓冲区读取,只有在完全读取了推回缓冲区里的内容,而且还没装满read方法中的数组形参时才会从源输入流中读取。
当我们创建PushbackInputStream/PushbackReader时需要制定推回缓冲区的大小,默认推回缓冲区的大小为1。如果推回缓冲区的大小超过了推回缓冲区的大小,程序就会引发Pushback buffer overflow的IOException
下面程序试图找出PushbackTest.java文件中的new PushbackTest字符串,找到该字符串后,程序只是打印出目标字符串之前的内容
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PushbackReader;
public class PushbackTest{
public static void main(String[] args){
PushbackReader pr=null;
try {
pr=new PushbackReader(new FileReader(".\\src\\PushbackTest.java"),128);
char[] cbuf=new char[64];
String lastContent="";
int hasRead=0;
while((hasRead=pr.read(cbuf))>0){
String content=new String(cbuf,0,hasRead);
int targetIndex=0;
if((targetIndex=(lastContent+content).indexOf("new PushbackReader"))>0){
pr.unread((lastContent+content).toCharArray());
pr.read(cbuf,0,targetIndex);
System.out.println(new String(cbuf,0,targetIndex));
return;
}else{
System.out.println(lastContent);
lastContent=content;
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(pr!=null){
try {
pr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
程序第一步先创建指定缓冲大小为128的PushbackReader对象,并创建一个长度为64的字符数组来保存每次读取的字符内容再申请一个为空的字符变量用来保存上一次读取的字符串内容,hashRead用来保存每次读取的字符个数。进入while方法先看判断条件:只要没把文件读完就执行;while条件中就执行了一次读的操作,并将读取的内容截取到恰好长度的字符保存到cbuf数组中,并将读取的字符个数返回给hasRead,一次读取完毕,一次while条件判断也完成了,接着执行while循环中的语句,首先将本次读取的字符数组cbuf从下标0开始长度为hasRead转换成字符串,接着申请一个targetIndex变量用来记录目标字符串在上次读取内容和这次读取内容出现的位置,前提是本次读取内容中包含了目标子字符串,其实记录的也是推回缓冲区后目标字符串出现的位置,
下面就是if判断了看这次读取的内容是否包含目标字符串,如果没有就执行else中的内容输出上次打印测内容,并将这次读入的内容复制给lastRead作为下次打印内容的上次读取内容,如果if条件满足那么就将上次读取内容和本次读取内容作连接运算,并求出目标字符串的位置赋值给targetIndex变量,紧接着
上次读取的字符串和本次读取的字符串作连接运算后退回缓冲区,然后再次调用read方法这次read的内容就是缓冲区的内容了,读取的内容刚好从0开始长度为target刚好把cbuf放满接着就处理读取的数组并打印完成程序,由于两次读取的字符长度刚好等于缓冲区长度而没有超过所以不会发生发生Pushback buffer overfow的IOException异常。
总的来看上面程序就是不断的读取固定长度的内容并打印出来,直到读取到目标字符串,满足if条件后就做两件事打印上次读取的内容,并推回推回输入流缓冲区。
while条件里面每次read方法后都有一个隐式的记录指针记录这次读取到的位置,作为下次读取的开始位置