# Java `InputStream`教程

原文：http://zetcode.com/java/inputstream/

Java `InputStream`教程显示了如何使用 Java 中的`InputStream`类。

Java 流是来自源或目的地的数据流。 Java 流的一个很好的比喻是水从水龙头流入浴缸，然后又流入排水装置。 `InputStream`和`OutputStream`是对数据（例如 C 文件指针）的低级访问的抽象。

## Java `InputStream`

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

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

## Java `InputStream`子类

`InputStream`是一个抽象类； 它是表示字节输入流的所有类的超类，包括`AudioInputStream`，`ByteArrayInputStream`，`FileInputStream`，`FilterInputStream`，`ObjectInputStream`，`PipedInputStream`和`SequenceInputStream`。

## Java `InputStream`关闭

`FileInputStream`的`close()`方法关闭输入流，并释放与此流关联的所有系统资源。 在我们的示例中，我们使用`try-with-resources`语句，该语句确保在语句末尾关闭每个资源。

## Java `InputStream`读取

`InputStream`使用以下读取方法读取字节：

*   `read(byte[] b)` - 从此输入流中读取最多`b.length`个字节的数据到一个字节数组中。
*   `read(byte[] b, int off, int len)` - 从此输入流中读取最多`len`个字节的数据到一个字节数组中。
*   `read()` - 从文件输入流中读取一个字节。

## Java `InputStream`读取文本

以下示例显示如何使用`InputStream`读取文本文件。

`thermopylae.txt`

```java
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. 

```

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

`JavaInputStreamText.java`

```java
package com.zetcode;

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;

public class JavaInputStreamText {

    public static void main(String[] args) throws IOException {

        String fileName = "src/resources/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));
        }
    }
}

```

使用`FileInputStream`，`InputStreamReader`和`BufferedReader`读取文本文件。

```java
try (InputStream fis = new FileInputStream(fileName);

```

`FileInputStream`是`InputStream`的一种特殊形式，用于从文件中读取字节。

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

```

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

```java
BufferedReader br = new BufferedReader(isr)) {

```

`BufferedReader`从字符输入流中读取文本，缓冲字符以有效读取字符，数组和行。

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

```

从缓冲读取器中按行读取数据。

## Java `InputStream`读取字节

`InputStream`的读取方法读取字节。

`JavaInputStreamBytes.java`

```java
package com.zetcode;

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

public class JavaInputStreamBytes {

    public static void main(String[] args) throws IOException {

        String fileName = "src/resources/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 图像读取字节，并将字节以十六进制格式打印到控制台。

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

```

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

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

```

使用`read()`方法，我们将字节读入字节数组。

```java
int i = 0;

for (byte b: buffer) {

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

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

    i++;
}

```

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

```java
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 读取 Java `InputStream`

`InputStream`允许从 URL 源读取数据。

`JavaInputStreamURL.java`

```java
package com.zetcode;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;

public class JavaInputStreamURL {

    public static void main(String[] args) throws IOException {

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

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

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

```

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

```java
try (InputStream is = url.openStream();

```

使用`openStream()`方法创建 URL 的`InputStream`。

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

```

这是输出。

## Java `InputStream`读取反序列化的数据

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

`Country.java`

```java
package com.zetcode;

import java.io.Serializable;

public class Country implements Serializable {

    static final long serialVersionUID = 42L;

    private String name;
    private int population;

    public Country(String name, int population) {
        this.name = name;
        this.population = population;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getPopulation() {
        return population;
    }

    public void setPopulation(int population) {
        this.population = population;
    }
}

```

这是`Country` bean。 我们将序列化和反序列化国家列表。

`JavaObjectOutputStreamEx.java`

```java
package com.zetcode;

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

public class JavaObjectOutputStreamEx {

    public static void main(String[] args) throws IOException {

        String fileName = "src/resources/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);
        }
    }
}

```

该示例序列化对象列表。

```java
out.writeObject(countries);

```

国家列表被写入`ObjectOutputStream`。

`JavaInputStreamObjects.java`

```java
package com.zetcode;

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

public class JavaInputStreamObjects {

    public static void main(String[] args) throws IOException, ClassNotFoundException {

        String fileName = "src/resources/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);
        }
    }
}

```

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

## Java `InputStream`读取流序列

`SequenceInputStream`代表一系列输入流。 它允许从多个有序流中读取。

`JavaInputStreamSequence.java`

```java
package com.zetcode;

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

public class JavaInputStreamSequence {

    public static void main(String[] args) throws IOException {

        String fileName1 = "src/resources/myfile.txt";
        String fileName2 = "src/resources/myfile1.txt";
        String fileName3 = "src/resources/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();
        }
    }
}

```

该示例从三个`FileInputStreams`中读取。

```java
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`中。

```java
int b = sis.read();

while (b != -1) {

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

```

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

在本教程中，我们介绍了 Java `InputStream`类。 您可能也对相关教程感兴趣： [Java `InputStreamReader`教程](/java/inputstreamreader/)， [Java `FileOutputStream`教程](/java/fileoutputstream/)， [Java `FileInputStream`教程](/java/fileinputstream/)， [Java 文件时间](/articles/javafiletime/)， [Java `FileWriter`教程](/java/filewriter/)， [Java 附加到文件](/articles/javaappendtofile/)，[用 Java 读取文本文件](/articles/javareadtext/)和 [Java 教程](/lang/java/)。