ZetCode

Java OutputStream 类

最后修改时间:2025 年 4 月 16 日

java.io.OutputStream 类是一个抽象超类,代表一个字节的输出流。它提供了将数据写入各种输出目标所需的基本方法。所有输出流类都继承自这个基类。

OutputStream 定义了字节输出操作的基本接口。具体子类为特定的目标(如文件、网络连接或内存缓冲区)实现这些方法。该类是 Java 核心 I/O 系统的一部分。

OutputStream 类概述

OutputStream 是一个抽象类,不能直接实例化。它为 Java 中的所有字节输出操作提供了模板。关键方法包括写入字节、刷新缓冲区和关闭流。

public abstract class OutputStream implements Closeable, Flushable {
    public abstract void write(int b) throws IOException;
    public void write(byte[] b) throws IOException;
    public void write(byte[] b, int off, int len) throws IOException;
    public void flush() throws IOException;
    public void close() throws IOException;
}

上面的代码显示了 OutputStream 提供的关键方法。这些方法必须由具体的子类实现。该类实现了 CloseableFlushable 接口,用于资源管理。

写入单个字节

最基本的操作是将单个字节写入输出流。write(int b) 方法写入整数参数的最低 8 位。高位被忽略。这是一个抽象方法,子类必须实现。

Main.java
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Main {

    public static void main(String[] args) {
        try (OutputStream os = new FileOutputStream("output.txt")) {
            
            // Write individual bytes
            os.write(72);  // H
            os.write(101); // e
            os.write(108); // l
            os.write(108); // l
            os.write(111); // o
            
            System.out.println("Bytes written successfully");
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

此示例演示了将单个字节写入文件。try-with-resources 语句确保流被正确关闭。每个 write 调用将一个字节输出到流。这些字节代表“Hello”的 ASCII 字符。

写入字节数组

为了获得更好的性能,您可以使用字节数组一次写入多个字节。write(byte[] b) 方法写入数组中的所有字节。还有一个版本写入数组的一部分。

Main.java
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Main {

    public static void main(String[] args) {
        try (OutputStream os = new FileOutputStream("output.txt")) {
            
            // Create byte array
            byte[] data = "Hello, OutputStream!".getBytes();
            
            // Write entire array
            os.write(data);
            
            // Write portion of array
            byte[] largeData = new byte[100];
            System.arraycopy(data, 0, largeData, 0, data.length);
            os.write(largeData, 0, data.length);
            
            System.out.println("Byte arrays written successfully");
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

此示例显示了两种写入字节数组的方式。首先,写入整个数组。然后,写入较大数组的一部分。 System.arraycopy 方法用于将数据复制到较大的数组中。这种方法比写入单个字节更有效。

刷新输出流

flush 方法强制将任何缓冲的输出字节写出。一些输出流为了提高性能而实现缓冲。刷新确保数据实际上被写入目标,而不是停留在缓冲区中。

Main.java
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Main {

    public static void main(String[] args) {
        try (OutputStream os = new BufferedOutputStream(
                new FileOutputStream("output.txt"))) {
            
            os.write("Important data".getBytes());
            
            // Force write to disk
            os.flush();
            
            System.out.println("Data written and flushed");
            
            // More writes
            os.write("More data".getBytes());
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

此示例演示了刷新缓冲的输出流。 flush 调用确保数据立即写入磁盘。如果不刷新,数据可能会保留在内存缓冲区中,直到流关闭或缓冲区已满。刷新对于关键数据很重要。

关闭输出流

close 方法释放与流关联的系统资源。关闭流以防止资源泄漏至关重要。try-with-resources 语句在块退出时自动关闭流。

Main.java
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Main {

    public static void main(String[] args) {
        OutputStream os = null;
        try {
            os = new FileOutputStream("output.txt");
            os.write("Test data".getBytes());
            System.out.println("Data written successfully");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (os != null) {
                try {
                    os.close();
                    System.out.println("Stream closed");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

此示例显示了在 finally 块中手动关闭流。流是在 try-with-resources 之外创建的,以演示正确的手动关闭。实际上,try-with-resources 是首选。关闭流会自动刷新任何缓冲的数据。

将 OutputStream 与缓冲结合使用

为了获得更好的性能,OutputStream 经常与 BufferedOutputStream 一起使用。这通过在内存中缓冲数据来减少物理写操作的数量。当缓冲区已满或流关闭时,缓冲区会自动刷新。

Main.java
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Main {

    public static void main(String[] args) {
        try (OutputStream os = new BufferedOutputStream(
                new FileOutputStream("largefile.dat"), 8192)) {
            
            // Write 1MB of data
            byte[] data = new byte[1024]; // 1KB buffer
            for (int i = 0; i < 1024; i++) { // 1024 * 1KB = 1MB
                os.write(data);
            }
            
            System.out.println("1MB of data written with buffering");
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

此示例演示了使用缓冲写入大量数据。 BufferedOutputStream 使用 8KB 缓冲区(默认值为 8KB,但我们明确设置了它)。使用缓冲写入许多小块更有效。可以根据性能要求调整缓冲区大小。

来源

Java OutputStream 类文档

在本文中,我们介绍了 Java OutputStream 类的基本方法和特性。理解这些概念对于在 Java 应用程序中处理输出操作至关重要。

作者

我的名字是 Jan Bodnar,是一位经验丰富的程序员,在该领域拥有多年经验。我于 2007 年开始撰写编程文章,此后撰写了 1,400 多篇文章和 8 本电子书。凭借超过八年的教学经验,我致力于分享我的知识并帮助他人掌握编程概念。

列出所有Java教程