Java PushbackInputStream 类
最后修改时间:2025 年 4 月 16 日
java.io.PushbackInputStream
类为另一个输入流添加了推回 (pushback) 功能。 它允许将读取的字节推回流中。 这对于需要在流中“窥视”的解析场景非常有用。
PushbackInputStream
封装了另一个 InputStream
,并为推回的字节提供了一个缓冲区。 默认的推回缓冲区大小为 1 字节,但可以指定自定义大小。 此类不是线程安全的,不能并发访问。
PushbackInputStream 类概述
PushbackInputStream
扩展了 FilterInputStream
并提供推回操作。 关键方法包括读取操作和 unread 方法,用于将字节推回。 推回缓冲区保存将要读取的字节。
public class PushbackInputStream extends FilterInputStream { public PushbackInputStream(InputStream in); public PushbackInputStream(InputStream in, int size); public int read(); public int read(byte[] b, int off, int len); public void unread(int b); public void unread(byte[] b); public void unread(byte[] b, int off, int len); public int available(); public long skip(long n); public boolean markSupported(); public void close(); }
上面的代码显示了 PushbackInputStream
提供的关键方法。 这些方法允许读取数据并将字节推回流中。 该类不支持 mark/reset 操作。
创建 PushbackInputStream
通过将 PushbackInputStream 封装在另一个 InputStream
中来创建它。 您可以指定推回缓冲区大小或使用默认的 1 字节缓冲区。 缓冲区大小决定了可以推回的字节数。
import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.PushbackInputStream; public class Main { public static void main(String[] args) { byte[] data = { 'A', 'B', 'C', 'D', 'E' }; try { // Create with default buffer size (1 byte) ByteArrayInputStream bais1 = new ByteArrayInputStream(data); PushbackInputStream pbis1 = new PushbackInputStream(bais1); // Create with custom buffer size (5 bytes) ByteArrayInputStream bais2 = new ByteArrayInputStream(data); PushbackInputStream pbis2 = new PushbackInputStream(bais2, 5); System.out.println("Default buffer stream created"); System.out.println("Custom buffer (5 bytes) stream created"); pbis1.close(); pbis2.close(); } catch (IOException e) { e.printStackTrace(); } } }
此示例演示了创建 PushbackInputStream 的不同方法。 第一个使用默认缓冲区大小(1 字节),而第二个指定 5 个字节。 完成后始终关闭流以释放资源。 关闭 PushbackInputStream 时会自动关闭底层流。
读取和推回单个字节
最简单的用例是读取一个字节,并在需要时将其推回。 unread 方法将字节放回流的缓冲区中。 这允许稍后重新读取相同的字节。
import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.PushbackInputStream; public class Main { public static void main(String[] args) { byte[] data = { 'A', 'B', 'C', 'D', 'E' }; try (PushbackInputStream pbis = new PushbackInputStream(new ByteArrayInputStream(data))) { // Read first byte int firstByte = pbis.read(); System.out.println("First byte: " + (char) firstByte); // Push it back pbis.unread(firstByte); System.out.println("Byte pushed back"); // Read again (same byte) int sameByte = pbis.read(); System.out.println("Read again: " + (char) sameByte); // Continue reading int nextByte; while ((nextByte = pbis.read()) != -1) { System.out.println("Next byte: " + (char) nextByte); } } catch (IOException e) { e.printStackTrace(); } } }
此示例显示了读取一个字节并将其推回流中。 下一次读取操作将返回推回的字节。 默认的 1 字节缓冲区足以满足此用例。 推回的字节数超过缓冲区大小会抛出 IOException。
推回多个字节
使用较大的缓冲区,可以推回多个字节。 unread 方法接受一个字节数组。 字节以相反的顺序推回(最后一个字节先推回)。
import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.PushbackInputStream; public class Main { public static void main(String[] args) { byte[] data = { '1', '2', '3', '4', '5' }; try (PushbackInputStream pbis = new PushbackInputStream(new ByteArrayInputStream(data), 3)) { // Read first three bytes byte[] buffer = new byte[3]; pbis.read(buffer); System.out.println("Read: " + new String(buffer)); // Push them back pbis.unread(buffer); System.out.println("Pushed back 3 bytes"); // Read again (same bytes) pbis.read(buffer); System.out.println("Read again: " + new String(buffer)); // Read remaining bytes int remaining; while ((remaining = pbis.read()) != -1) { System.out.println("Remaining: " + (char) remaining); } } catch (IOException e) { e.printStackTrace(); } } }
此示例演示了推回多个字节。 该流创建时具有 3 字节缓冲区。 读取 3 个字节后,它们被推回并再次读取。 请注意,推回的字节数超过缓冲区大小会抛出异常。
使用 PushbackInputStream 进行解析
PushbackInputStream 通常用于解析场景。 您可以提前读取以检查数据,然后如果字节与预期模式不匹配,则将字节推回。 这实现了灵活的解析,而不会消耗字节。
import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.PushbackInputStream; public class Main { public static void main(String[] args) { String data = "123ABC456DEF"; byte[] bytes = data.getBytes(); try (PushbackInputStream pbis = new PushbackInputStream(new ByteArrayInputStream(bytes), 10)) { int b; while ((b = pbis.read()) != -1) { if (Character.isDigit((char) b)) { System.out.println("Number: " + (char) b); } else { // Push back the non-digit pbis.unread(b); // Read the alphabetic sequence StringBuilder letters = new StringBuilder(); while ((b = pbis.read()) != -1 && Character.isLetter((char) b)) { letters.append((char) b); } // Push back the non-letter if not EOF if (b != -1) pbis.unread(b); System.out.println("Letters: " + letters); } } } catch (IOException e) { e.printStackTrace(); } } }
此示例演示了解析混合的数字和字母数据。 当找到非数字时,它被推回,然后读取字母序列。 解析器根据窥视的字节在数字和字母处理之间切换。
处理推回缓冲区溢出
尝试推回超过缓冲区大小的字节数会抛出 IOException。 使用推回操作时,需要进行适当的错误处理。 在 unread 之前始终检查缓冲区容量。
import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.PushbackInputStream; public class Main { public static void main(String[] args) { byte[] data = { 'X', 'Y', 'Z' }; try (PushbackInputStream pbis = new PushbackInputStream(new ByteArrayInputStream(data), 2)) { // Read two bytes byte[] buffer = new byte[2]; pbis.read(buffer); System.out.println("Read: " + new String(buffer)); // Push them back (okay) pbis.unread(buffer); System.out.println("Pushed back 2 bytes"); try { // Try to push back one more byte (will overflow) pbis.unread('W'); System.out.println("This won't be printed"); } catch (IOException e) { System.out.println("Caught IOException: " + e.getMessage()); } // Continue reading int remaining; while ((remaining = pbis.read()) != -1) { System.out.println("Remaining: " + (char) remaining); } } catch (IOException e) { e.printStackTrace(); } } }
此示例演示了缓冲区溢出处理。 2 字节缓冲区允许推回两个字节。 尝试推回第三个字节会抛出 IOException。 适当的错误处理确保程序能够正常继续。
将 Pushback 与其他流结合使用
PushbackInputStream 可以与其他流类型结合使用,以进行复杂的 I/O 操作。 它通常与缓冲流一起使用以获得更好的性能。 推回功能的工作方式与底层流无关。
import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.PushbackInputStream; public class Main { public static void main(String[] args) { byte[] data = new byte[100]; for (int i = 0; i < data.length; i++) { data[i] = (byte) (i % 26 + 'A'); } try (PushbackInputStream pbis = new PushbackInputStream( new BufferedInputStream( new ByteArrayInputStream(data)), 10)) { // Read first 10 bytes byte[] buffer = new byte[10]; pbis.read(buffer); System.out.println("First 10: " + new String(buffer)); // Push them back pbis.unread(buffer); // Read again with different chunk size byte[] smallBuffer = new byte[3]; pbis.read(smallBuffer); System.out.println("First 3 after pushback: " + new String(smallBuffer)); // Read remaining int bytesRead; while ((bytesRead = pbis.read(buffer)) != -1) { System.out.println("Read " + bytesRead + " bytes: " + new String(buffer, 0, bytesRead)); } } catch (IOException e) { e.printStackTrace(); } } }
此示例显示了 PushbackInputStream 封装了一个 BufferedInputStream。 这种组合提供了缓冲和推回功能。 推回操作的工作方式与底层缓冲流无关。
来源
在本文中,我们介绍了 Java PushbackInputStream 类的基本方法和特性。 理解这些概念对于在 Java I/O 中进行解析和超前查看操作至关重要。
作者
列出所有Java教程。