Java ByteArrayInputStream 类
最后修改时间:2025 年 4 月 16 日
java.io.ByteArrayInputStream
类允许从字节数组中读取字节,将其作为输入流。 它是 Java I/O 包的一部分,并提供了一个内存中的流实现。 当使用字节数组作为流时,此类非常有用。
ByteArrayInputStream
扩展了 InputStream
并封装了一个字节数组。 它维护一个内部位置计数器来跟踪读取进度。 可以重置流以重新读取数据。 与文件流不同,它不需要外部资源。
ByteArrayInputStream 类概述
ByteArrayInputStream
为字节数组提供流功能。 主要方法包括标准读取操作、标记/重置和流跳过。 该类不需要关闭,但为了兼容性而实现了 Closeable。
public class ByteArrayInputStream extends InputStream { public ByteArrayInputStream(byte[] buf); public ByteArrayInputStream(byte[] buf, int offset, int length); public synchronized int read(); public synchronized int read(byte[] b, int off, int len); public synchronized long skip(long n); public synchronized int available(); public synchronized void mark(int readAheadLimit); public synchronized void reset(); public boolean markSupported(); public void close(); }
上面的代码显示了 ByteArrayInputStream
的关键方法。 该类支持所有标准的 InputStream 操作。 标记/重置功能始终可用。 缓冲区不会被复制,而是被流引用。
创建 ByteArrayInputStream
通过将字节数组传递给其构造函数来创建 ByteArrayInputStream。 您可以指定整个数组或一部分。 流在原始数组上运行 - 对数组的更改会影响流。
import java.io.ByteArrayInputStream; import java.io.IOException; public class Main { public static void main(String[] args) { byte[] data = {65, 66, 67, 68, 69, 70}; // A-F in ASCII // Create stream from full array ByteArrayInputStream stream1 = new ByteArrayInputStream(data); // Create stream from portion (bytes 2-4) ByteArrayInputStream stream2 = new ByteArrayInputStream(data, 2, 3); try { System.out.println("Stream1 contents:"); while (stream1.available() > 0) { System.out.print((char) stream1.read() + " "); } System.out.println("\n\nStream2 contents:"); while (stream2.available() > 0) { System.out.print((char) stream2.read() + " "); } } catch (IOException e) { e.printStackTrace(); } } }
此示例显示了创建 ByteArrayInputStream 的两种方法。 第一个使用整个数组,而第二个使用一部分。 输出显示了不同的内容。 请注意,IOException 的可能性很小,但必须处理。
读取单个字节
从 ByteArrayInputStream 读取的最简单方法是逐字节读取。 read 方法在流的末尾返回 -1。 每次调用都会前进内部位置。 这种方法很简单,但不适用于大型数据。
import java.io.ByteArrayInputStream; import java.io.IOException; public class Main { public static void main(String[] args) { String text = "Hello ByteArrayInputStream"; byte[] bytes = text.getBytes(); try (ByteArrayInputStream stream = new ByteArrayInputStream(bytes)) { int byteData; System.out.println("Reading bytes:"); while ((byteData = stream.read()) != -1) { System.out.print((char) byteData + "(" + byteData + ") "); } System.out.println("\n\nReading complete"); } catch (IOException e) { e.printStackTrace(); } } }
此示例从 ByteArrayInputStream 中以字节形式读取一个字符串。 每个字节都以字符和数值形式打印。 try-with-resources 确保正确关闭流。 虽然 ByteArrayInputStream 不需要,但这是一个好习惯。
将字节读入数组
为了获得更好的性能,一次读取多个字节到一个字节数组中。 这减少了方法调用,效率更高。 read 方法返回实际读取的字节数。
import java.io.ByteArrayInputStream; import java.io.IOException; public class Main { public static void main(String[] args) { String text = "Reading bytes in bulk is more efficient"; byte[] source = text.getBytes(); try (ByteArrayInputStream stream = new ByteArrayInputStream(source)) { byte[] buffer = new byte[10]; int bytesRead; System.out.println("Reading in chunks:"); while ((bytesRead = stream.read(buffer)) != -1) { String chunk = new String(buffer, 0, bytesRead); System.out.println("Read " + bytesRead + " bytes: " + chunk); } } catch (IOException e) { e.printStackTrace(); } } }
此示例演示了批量读取到 10 字节的缓冲区中。 String 构造函数将每个块转换为文本。 bytesRead 值确保仅处理实际数据。 对于大型数据集,这种方法要快得多。
Mark 和 Reset 功能
ByteArrayInputStream 完全支持标记和重置操作。 mark 方法记住当前位置。 Reset 返回到此位置,允许重新读取数据。 readAheadLimit 参数被忽略。
import java.io.ByteArrayInputStream; import java.io.IOException; public class Main { public static void main(String[] args) { byte[] data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; try (ByteArrayInputStream stream = new ByteArrayInputStream(data)) { // Read first 3 bytes System.out.println("First 3 bytes:"); for (int i = 0; i < 3; i++) { System.out.print(stream.read() + " "); } // Mark current position stream.mark(100); // Parameter is ignored // Read next 3 bytes System.out.println("\n\nNext 3 bytes:"); for (int i = 0; i < 3; i++) { System.out.print(stream.read() + " "); } // Reset to mark stream.reset(); // Read again from mark System.out.println("\n\nAfter reset, next 3 bytes:"); for (int i = 0; i < 3; i++) { System.out.print(stream.read() + " "); } } catch (IOException e) { e.printStackTrace(); } } }
此示例显示了标记/重置功能。 读取 3 个字节后,我们标记该位置。 读取 3 个字节后,reset 返回到标记。 readAheadLimit 参数在 ByteArrayInputStream 中被忽略。
跳过流中的字节
skip 方法在不读取的情况下将流位置向前移动。 它返回实际跳过的字节数。 这比读取和丢弃数据更有效。
import java.io.ByteArrayInputStream; import java.io.IOException; public class Main { public static void main(String[] args) { String text = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; byte[] bytes = text.getBytes(); try (ByteArrayInputStream stream = new ByteArrayInputStream(bytes)) { System.out.println("Initial position: " + stream.available()); // Skip first 5 bytes long skipped = stream.skip(5); System.out.println("Skipped " + skipped + " bytes"); System.out.println("Next byte: " + (char) stream.read()); // Try to skip beyond end skipped = stream.skip(20); System.out.println("Skipped " + skipped + " bytes (end approached)"); System.out.println("Remaining: " + stream.available()); } catch (IOException e) { e.printStackTrace(); } } }
此示例演示了跳过字节。 第一个 skip 移动到前 5 个字母之后。 第二个尝试跳过 20 个字节,但仅跳过剩余的字节。 available 方法显示了剩余要读取的字节。
可用字节和位置
available 方法返回流中剩余的字节数。 这对于检查流状态很有用。 ByteArrayInputStream 还通过此方法提供位置跟踪。
import java.io.ByteArrayInputStream; import java.io.IOException; 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; } try (ByteArrayInputStream stream = new ByteArrayInputStream(data)) { System.out.println("Initial available: " + stream.available()); // Read 10 bytes byte[] buffer = new byte[10]; stream.read(buffer); System.out.println("After reading 10 bytes: " + stream.available()); // Skip 20 bytes stream.skip(20); System.out.println("After skipping 20 bytes: " + stream.available()); // Read remaining while (stream.available() > 0) { stream.read(buffer); System.out.println("Read 10 bytes, remaining: " + stream.available()); } } catch (IOException e) { e.printStackTrace(); } } }
此示例使用 available 跟踪流位置。 每次操作后,剩余字节数都会减少。 该方法为 ByteArrayInputStream 提供精确计数。 这与其他流不同,其他流中的 available 是一个估计值。
来源
在本文中,我们介绍了 Java ByteArrayInputStream 类的基本方法和特性。 理解这些概念对于在 Java 应用程序中使用内存中的字节数据作为流至关重要。
作者
列出所有Java教程。