ZetCode

Java InputStream

最后修改日期:2024年2月21日

在本文中,我们将展示如何在 Java 中使用 InputStream 类。

Java 流是从源到目标的数据流。 Java 流的一个很好的比喻是水从水龙头流入浴缸,然后流入排水管。 InputStreamOutputStream 是对底层数据访问的抽象,例如 C 文件指针。

InputStream 是用于读取数据的源。流可以表示各种类型的源,包括磁盘文件、设备、其他程序和内存数组。

流支持许多不同的数据类型,包括简单字节、原始数据类型、本地化字符和对象。

子类

InputStream 是一个抽象类;它是表示字节输入流的所有类的超类,包括 AudioInputStreamByteArrayInputStreamFileInputStreamFilterInputStreamObjectInputStreamPipedInputStreamSequenceInputStream

close 方法

FileInputStreamclose 方法关闭输入流并释放与此流关联的任何系统资源。在我们的示例中,我们使用try-with-resources语句,以确保每个资源在语句结束时都会关闭。

read 方法

InputStream 使用以下 read 方法读取字节

读取文本

以下示例展示了如何使用 InputStream 读取文本文件。

thermopylae.txt
The Battle of Thermopylae was fought between an alliance of Greek city-states,
led by King Leonidas of Sparta, and the Persian Empire of Xerxes I over the
course of three days, during the second Persian invasion of Greece.

在此示例中,我们使用此文本文件。

Main.java
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;

void main() throws IOException {

    String fileName = "thermopylae.txt";

    try (InputStream fis = new FileInputStream(fileName);
            InputStreamReader isr = new InputStreamReader(fis, StandardCharsets.UTF_8);
            BufferedReader br = new BufferedReader(isr)) {

        br.lines().forEach(line -> System.out.println(line));
    }
}

文本文件通过 FileInputStreamInputStreamReaderBufferedReader 读取。

try (InputStream fis = new FileInputStream(fileName);

FileInputStreamInputStream 的一个特化,用于从文件读取字节。

InputStreamReader isr = new InputStreamReader(fis, StandardCharsets.UTF_8);

InputStreamReader 是从字节流到字符流的桥梁:它读取字节并使用指定的字符集将其解码为字符。

BufferedReader br = new BufferedReader(isr)) {

BufferedReader 从字符输入流中读取文本,缓冲字符以高效地读取字符、数组和行。

br.lines().forEach(line -> System.out.println(line));

数据通过缓冲读取器按行读取。

读取字节

InputStream 的 read 方法读取字节。

Main.java
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

void main() throws IOException {

    String fileName = "ball.png";

    try (InputStream is = new FileInputStream(fileName)) {

        byte[] buffer = new byte[is.available()];
        is.read(buffer);

        int i = 0;

        for (byte b : buffer) {

            if (i % 10 == 0) {
                System.out.println();
            }

            System.out.printf("%02x ", b);

            i++;
        }
    }

    System.out.println();
}

该示例从 PNG 图像读取字节,并将字节以十六进制格式打印到控制台。

try (InputStream is = new FileInputStream(fileName)) {

我们使用 FileInputStream 从图像文件读取字节。

byte[] buffer = new byte[is.available()];
is.read(buffer);

使用 read 方法,我们将字节读取到字节数组中。

int i = 0;

for (byte b: buffer) {

    if (i % 10 == 0) {
        System.out.println();
    }

    System.out.printf("%02x ", b);

    i++;
}

我们遍历数组并将字节以十六进制格式打印到控制台。

89 50 4e 47 0d 0a 1a 0a 00 00
00 0d 49 48 44 52 00 00 00 0a
00 00 00 0a 08 06 00 00 00 8d
32 cf bd 00 00 00 04 73 42 49
54 08 08 08 08 7c 08 64 88 00
00 00 09 70 48 59 73 00 00 0d
d7 00 00 0d d7 01 42 28 9b 78
00 00 00 19 74 45 58 74 53 6f
...

这是该示例的部分样本输出。

从 URL 读取

InputStream 允许从 URL 源读取数据。

Main.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URI;
import java.net.URISyntaxException;

void main() throws IOException, URISyntaxException {

    String webSite = "https://www.something.com";
    URL url = new URI(webSite).toURL();

    try (InputStream is = url.openStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is))) {

        br.lines().forEach(System.out::println);
    }
}

该示例打开到网页的 InputStream 并读取其数据。

try (InputStream is = url.openStream();

使用 openStream 方法创建到 URL 的 InputStream

<html><head><title>Something.</title></head>
<body>Something.</body>
</html>

读取反序列化数据

ObjectInputStream 读取先前使用 ObjectOutputStream 写入的序列化数据。

Main.java
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

void main() throws IOException {

    String fileName = "myfile.dat";

    try (OutputStream fis = new FileOutputStream(fileName);
            ObjectOutputStream out = new ObjectOutputStream(fis)) {

        List<Country> countries = new ArrayList<>();
        countries.add(new Country("Slovakia", 5429000));
        countries.add(new Country("Norway", 5271000));
        countries.add(new Country("Croatia", 4225000));
        countries.add(new Country("Russia", 143439000));

        out.writeObject(countries);
    }
}

record Country(String name, int population) implements Serializable {}

该示例序列化一个对象列表。

out.writeObject(countries);

国家/地区的列表写入到 ObjectOutputStream

Main.java
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.List;

void main() throws IOException, ClassNotFoundException {

    String fileName = "myfile.dat";

    try (InputStream fis = new FileInputStream(fileName);
            ObjectInputStream oin = new ObjectInputStream(fis)) {

        List<Country> countries = (List<Country>) oin.readObject();

        countries.forEach(System.out::println);
    }
}

record Country(String name, int population) implements Serializable {}

我们使用 ObjectInputStream 读取序列化数据。

读取流序列

SequenceInputStream 表示输入流的序列。它允许从多个有序流中读取。

Main.java
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.SequenceInputStream;

void main() throws IOException {

    String fileName1 = "myfile.txt";
    String fileName2 = "myfile1.txt";
    String fileName3 = "myfile2.txt";

    try (InputStream is1 = new FileInputStream(fileName1);
            InputStream is2 = new FileInputStream(fileName2);
            InputStream is3 = new FileInputStream(fileName3);
            SequenceInputStream sis1 = new SequenceInputStream(is1, is2);
            SequenceInputStream sis = new SequenceInputStream(sis1, is3)) {

        int b = sis.read();

        while (b != -1) {

            System.out.printf("%c", b);
            b = sis.read();
        }

        System.out.println();
    }
}

该示例从三个 FileInputStream 读取。

try (InputStream is1 = new FileInputStream(fileName1);
        InputStream is2 = new FileInputStream(fileName2);
        InputStream is3 = new FileInputStream(fileName3);
        SequenceInputStream sis1 = new SequenceInputStream(is1, is2);
        SequenceInputStream sis = new SequenceInputStream(sis1, is3)) {

我们定义了三个输入流,并将这些流放入 SequenceInputStreams 中。

int b = sis.read();

while (b != -1) {

    System.out.printf("%c", b);
    b = sis.read();
}

我们使用 read 从流中读取数据。

来源

Java InputStream - 语言参考

在本文中,我们介绍了 Java InputStream 类。

作者

我叫 Jan Bodnar,是一位热情的程序员,拥有丰富的编程经验。 我自 2007 年以来一直撰写编程文章。迄今为止,我已经撰写了 1,400 多篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有Java教程