Java InputStream 类
最后修改时间:2025 年 4 月 16 日
java.io.InputStream
类是一个抽象超类,表示字节的输入流。它是 Java 中所有字节输入流的基础。具体的子类实现了特定的输入源,例如文件、网络连接或内存缓冲区。
InputStream
提供了从各种源读取字节的基本方法。它支持基本的读取操作、流标记、跳过和资源管理。所有方法都会在发生 I/O 错误时抛出 IOException
。
InputStream 类概述
InputStream
是一个抽象类,它定义了读取字节的核心功能。主要方法包括各种读取操作、流控制和资源管理。子类必须至少实现基本的 read 方法。
public abstract class InputStream implements Closeable { public abstract int read() throws IOException; public int read(byte[] b) throws IOException; public int read(byte[] b, int off, int len) throws IOException; public long skip(long n) throws IOException; public int available() throws IOException; public void close() throws IOException; public synchronized void mark(int readlimit); public synchronized void reset() throws IOException; public boolean markSupported(); }
上面的代码展示了 InputStream
提供的关键方法。这些方法构成了 Java 中所有字节输入操作的基础。抽象的 read
方法必须由具体的子类实现。
读取单个字节
最基本的操作是从流中读取单个字节。read 方法将字节作为 int (0-255) 返回,或者在流的末尾返回 -1。此方法会阻塞,直到输入可用或到达流的末尾。
import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; public class Main { public static void main(String[] args) { byte[] data = {65, 66, 67, 68, 69}; // ABCDE try (InputStream is = new ByteArrayInputStream(data)) { int byteRead; while ((byteRead = is.read()) != -1) { System.out.println("Read byte: " + byteRead + " (" + (char) byteRead + ")"); } System.out.println("End of stream reached"); } catch (IOException e) { e.printStackTrace(); } } }
此示例演示了从 ByteArrayInputStream
读取字节。try-with-resources 确保正确关闭流。每个字节都以数值和字符的形式打印。循环会一直持续到 read 返回 -1,表示流的末尾。
将字节读入数组
为了获得更好的性能,一次性将多个字节读入字节数组。这减少了方法调用并提高了效率。read 方法返回实际读取的字节数,或者在流的末尾返回 -1。
import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; public class Main { public static void main(String[] args) { String text = "Hello, InputStream!"; byte[] data = text.getBytes(); try (InputStream is = new ByteArrayInputStream(data)) { byte[] buffer = new byte[10]; int bytesRead; while ((bytesRead = is.read(buffer)) != -1) { System.out.println("Read " + bytesRead + " bytes: " + new String(buffer, 0, bytesRead)); } } catch (IOException e) { e.printStackTrace(); } } }
此示例展示了批量读取到 10 字节的缓冲区中。String 构造函数仅将实际读取的字节转换为文本。循环会一直持续到 read 返回 -1。每次迭代最多处理 10 个字节。
跳过流中的字节
skip 方法允许跳过指定数量的字节。这比读取和丢弃数据更有效。实际跳过的字节数可能小于请求的数量。
import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; 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 (InputStream is = new ByteArrayInputStream(data)) { System.out.println("Available before skip: " + is.available()); long skipped = is.skip(50); System.out.println("Skipped " + skipped + " bytes"); System.out.println("Next byte: " + is.read()); System.out.println("Available after skip: " + is.available()); } catch (IOException e) { e.printStackTrace(); } } }
此示例创建了一个 100 字节的流,并跳过前 50 个字节。available 方法显示跳过之前和之后剩余的字节数。跳过后的读取显示跳过部分后的第一个字节 (50)。
Mark 和 Reset 功能
某些 InputStream 实现支持 mark/reset 操作。这允许在提前读取后返回到标记的位置。mark 方法指定在标记失效之前可以读取多少字节。
import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; public class Main { public static void main(String[] args) { String text = "Markable InputStream Example"; try (InputStream is = new ByteArrayInputStream(text.getBytes())) { if (is.markSupported()) { System.out.println("Mark supported"); // Read and mark after 5 bytes byte[] buffer = new byte[5]; is.read(buffer); System.out.println("First 5 bytes: " + new String(buffer)); is.mark(10); // Mark with readlimit of 10 bytes // Read next 5 bytes is.read(buffer); System.out.println("Next 5 bytes: " + new String(buffer)); // Reset to mark position is.reset(); // Read again from mark is.read(buffer); System.out.println("After reset: " + new String(buffer)); } else { System.out.println("Mark not supported"); } } catch (IOException e) { e.printStackTrace(); } } }
此示例演示了 ByteArrayInputStream 的 mark/reset 功能。在读取 5 个字节后,我们标记该位置。读取超过 readlimit (10 字节) 会使标记失效。reset 返回到标记的位置。
从文件读取
FileInputStream 是一个常见的 InputStream 实现,用于读取文件。它直接从文件系统中的文件读取字节。始终关闭文件流以释放系统资源。
import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; public class Main { public static void main(String[] args) { try (InputStream is = new FileInputStream("example.txt")) { System.out.println("Available bytes: " + is.available()); byte[] buffer = new byte[1024]; int bytesRead; StringBuilder content = new StringBuilder(); while ((bytesRead = is.read(buffer)) != -1) { content.append(new String(buffer, 0, bytesRead)); } System.out.println("File content:\n" + content.toString()); } catch (IOException e) { e.printStackTrace(); } } }
此示例使用 FileInputStream 读取文件。available 方法给出初始文件大小。我们将数据块读入缓冲区并在 StringBuilder 中构建内容。try-with-resources 确保正确关闭文件句柄。
可用字节和流状态
available 方法估计可以读取而不会阻塞的字节数。对于文件,这通常意味着剩余字节。该方法对于检查流状态和进度很有用。
import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; public class Main { public static void main(String[] args) { byte[] data = new byte[1000]; try (InputStream is = new ByteArrayInputStream(data)) { System.out.println("Initial available: " + is.available()); byte[] buffer = new byte[100]; is.read(buffer); System.out.println("After reading 100 bytes: " + is.available()); is.skip(300); System.out.println("After skipping 300 bytes: " + is.available()); is.read(new byte[500]); System.out.println("After reading 500 bytes: " + is.available()); } catch (IOException e) { e.printStackTrace(); } } }
此示例在各种流操作期间跟踪可用字节。初始计数显示完整的流大小。每个读取或跳过操作都会减少可用计数。该方法有助于监控读取进度。
来源
在本文中,我们介绍了 Java InputStream 类的基本方法和特性。理解这些概念对于在 Java 应用程序中使用面向字节的输入操作至关重要。
作者
列出所有Java教程。