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教程。