在 Java 的 I/O 中,java.io.PushbackReader 类有着重要的用途,它主要用于解析来自 Reader 的数据。在实际的数据解析过程中,常常会遇到这样的情况:在确定如何解读当前字符时,需要提前读取后续的几个字符,以此来了解即将出现的字符信息,从而更准确地进行处理。而 PushbackReader 就为我们提供了这样的便利。
PushbackReader 具备一个强大的功能,即允许将已经读取的字符回推到 Reader 中。当调用 read() 方法读取字符时,如果后续发现某些字符提前读取了,不符合当前的解析步骤,就可以使用回推功能将这些字符重新放回 Reader。这样一来,当下次再次调用 read() 方法时,这些被回推的字符会再次被读取,从而实现了灵活的数据读取和处理。
值得一提的是,PushbackReader 的工作原理和 PushbackInputStream 十分相似。不过,二者存在本质区别,PushbackReader 专注于处理字符数据,而 PushbackInputStream 则主要处理字节数据。这种差异使得它们在不同的数据处理场景中各展所长,满足多样化的编程需求。
以下是一个简单的 PushbackReader 示例:
package com.hxstrive.java_io; import java.io.FileReader; import java.io.PushbackReader; public class PushbackReaderExample { public static void main(String[] args) throws Exception { try(PushbackReader pushbackReader = new PushbackReader(new FileReader("input.txt"))) { // 读取数据 int data = pushbackReader.read(); System.out.println("data=" + (char)data); // 退回 pushbackReader.unread(data); // 再次读取 data = pushbackReader.read(); System.out.println("data=" + (char)data); } } //输出: //data=你 //data=你 }
上述示例中,调用 read() 就像从其他读取器读取字符一样,从 PushbackReader 读取字符。调用 unread() 会将一个字符推回 PushbackReader。下次调用 read() 时,将首先读取被推回的字符。如果向 PushbackReader 推回多个字符,则会像堆栈一样,首先从 read() 方法返回最新推回的字符。
若想使用 PushbackReader 进行字符读取操作,首要任务是创建一个 PushbackReader 实例。在 Java 里,创建该实例需采用标准的对象实例化方式,也就是通过 new 操作符来实现。
值得注意的是,PushbackReader 自身并不直接产生字符流,而是对另一个 Reader 进行包装,以提供回退读取的功能。因此,在调用 PushbackReader 构造函数时,必须为其传入一个 Reader 对象,后续 PushbackReader 会从这个 Reader 中读取字符。
下面为你展示创建 PushbackReader 的示例:
PushbackReader pushbackReader = new PushbackReader(new FileReader("input.txt"))
上面示例,向 PushbackReader 构造函数传递了一个 FileReader。这将使 PushbackReader 从该 FileReader 中读取字符。
你可以在 PushbackReader 的构造函数中设置未读字符数。下面是如何使用 PushbackReader 构造函数设置推回限制:
int pushbackLimit = 8; PushbackReader reader = new PushbackReader( new FileReader("input.txt"), pushbackLimit);
上述示例,在 PushbackReader 中设置了一个 8 个字符的内部缓冲区。这意味着在再次读取之前,每次最多只能解读 8 个字符。
从 PushbackReader 读取字符就像从 Reader 读取字符一样,因为 PushbackReader 是 Reader 的子类。换句话说,你可以使用从 Reader 类继承的 read() 方法。下面是一个通过 read() 方法从 PushbackReader 读取字符的示例:
try(PushbackReader pushbackReader = new PushbackReader(new FileReader("input.txt"))) { int aChar = pushbackReader.read(); while(aChar != -1) { System.out.println((char) aChar); aChar = pushbackReader.read(); } }
上面示例,read() 方法会返回一个 int 值,你必须自己将其转换为字符(char)。当 PushbackReader 中没有可用字符时,read() 方法将返回 int 类型的值 -1。
要将字符推回 PushbackReader,必须调用其 unread() 方法。下面是一个将字符推回 PushbackReader 的示例:
int aChar = pushbackReader.read(); // 读取一个字符 pushbackReader.unread(aChar); // 将读取的字符推回去 aChar = pushbackReader.read(); // 读取被推回的字符
上述示例中,从 PushbackReader 读取一个字符,然后将其推回 PushbackReader,再从 PushbackReader 读取该字符。
当你完成从 PushbackReader 中读取字符后,必须记得关闭它。关闭 PushbackReader 也会关闭 PushbackReader 正在读取的 Reader 实例。
关闭 PushbackReader 仅需要调用其 close() 方法。下面是关闭 PushbackReader 的过程:
pushbackReader.close();
你还可以使用 Java7 中引入的 try-with-resources 结构。以下是如何使用 try-with-resources 结构来关闭 PushbackReader:
Reader reader = new FileReader("input.txt"); try(PushbackReader pushbackReader = new PushbackReader(reader)){ int data = pushbackReader.read(); while(data != -1) { System.out.print((char) data); data = pushbackReader.read(); } }
注意,上述示例,第一个 FileReader 实例并没有在 try-with-resources 代码块中创建。这意味着 try-with-resources 块不会自动关闭 FileReader 实例。不过,当 PushbackReader 关闭时,它也会关闭它所读取的 Reader 实例,因此 FileReader 实例会在 PushbackReader 关闭时被关闭。