探究Java的磁盘写入神器:OutputStream详解

举报
bug菌 发表于 2023/10/18 12:24:15 2023/10/18
【摘要】 🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,助你一臂之力,带你早日登顶🚀,欢迎大家关注&&收藏!持续更新中,up!up!up!!

🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,助你一臂之力,带你早日登顶🚀,欢迎大家关注&&收藏!持续更新中,up!up!up!!

环境说明:Windows 10 + IntelliJ IDEA 2021.3.2 + Jdk 1.8

前言

  在Java开发中,我们往往需要将程序中生成的数据或者结果保存在磁盘文件中,这时我们就需要使用到Java的输入输出流。

  在输入输出流中,OutputStream是Java中最为常用的输出流,它能够将数据流输出到目标设备中,例如磁盘文件、网络等。

  本文将对Java中的OutputStream进行详细介绍,包括它的作用、使用方法、源代码等内容,帮助读者更好地掌握这一重要的输出流。

摘要

  本文主要介绍了Java中的OutputStream,包括它的作用、使用方法、源代码等内容。具体而言,本文将从以下几个方面进行介绍:

  1. OutputStream的概述和作用;
  2. OutputStream的使用方法,包括如何创建OutputStream对象、如何使用OutputStream输出数据、如何关闭OutputStream
  3. OutputStream的源代码分析;
  4. 演示代码和测试用例;
  5. 小结和总结。

OutputStream

概述和作用

  OutputStream是Java中的一个抽象类,它是所有输出流的父类,用于写入数据流到目标设备中。OutputStream提供了一系列的方法,可以用于输出不同类型的数据到目标设备中。

OutputStream的主要作用包括:

  1. 写入二进制数据:OutputStream可以将二进制数据流写入到目标设备中,例如将图片、视频等二进制文件写入到磁盘文件中;
  2. 写入字符数据:OutputStream可以将字符数据流写入到目标设备中,例如将字符串写入到文本文件中;
  3. 写入网络数据:OutputStream可以将网络数据流写入到目标设备中,例如将数据发送给服务器。

方法源码解析

  Java的OutputStream类是所有输出流的父类,它提供了基本的输出操作,如write()flush()等方法。下面对其源码进行分析。

  1. 类的声明
public abstract class OutputStream implements Closeable, Flushable {
    ...
}

  OutputStream是一个抽象类,实现了CloseableFlushable接口,这表明它的子类可以被关闭和刷新。

  1. 常量
private static final int MAX_SKIP_BUFFER_SIZE = 2048;

  MAX_SKIP_BUFFER_SIZEOutputStream类中定义的私有常量,其值为2048,表示跳过数据时最大的缓存大小。

  1. 构造方法

  OutputStream类没有任何的构造方法,意味着它本身不能直接被实例化,只能通过其子类进行实例化。

  1. write()方法
public abstract void write(int b) throws IOException;

  write()方法是OutputStream类的最核心的方法,用来写入一个字节到输出流中。该方法抛出IOException异常,表示写入过程中可能会产生异常。

  1. write(byte[] b)方法
public void write(byte b[]) throws IOException {
    write(b, 0, b.length);
}

  write(byte[] b)方法是将字节数组b的所有字节写入到输出流中。其底层调用了write(byte[] b, int off, int len)方法。

  1. write(byte[] b, int off, int len)方法
public void write(byte b[], int off, int len) throws IOException {
    if (b == null) {
        throw new NullPointerException();
    } else if ((off < 0) || (off > b.length) || (len < 0) ||
               ((off + len) > b.length) || ((off + len) < 0)) {
        throw new IndexOutOfBoundsException();
    } else if (len == 0) {
        return;
    }
    for (int i = 0 ; i < len ; i++) {
        write(b[off + i]);
    }
}

  write(byte[] b, int off, int len)方法是将字节数组b中从偏移量off开始的len个字节写入到输出流中。该方法抛出IOException异常,表示写入过程中可能会产生异常。

  1. flush()方法
public void flush() throws IOException {}

  flush()方法是将所有的数据刷新到输出流中,以保证数据完整性。该方法抛出IOException异常,表示刷新过程中可能会产生异常。

  1. close()方法
public void close() throws IOException {}

  close()方法是关闭输出流的方法,释放相关系统资源。该方法抛出IOException异常,表示关闭过程中可能会产生异常。

优缺点

OutputStream是Java中的一个抽象类,它是所有输出流的超类。OutputStream的主要作用是将数据从Java程序输出到外部设备或文件中。

优点:

  1. 输出流可以将数据写入到各种不同的设备和文件中,如磁盘文件、网络连接和内存缓冲区等。
  2. OutputStream是一个抽象类,可以实现不同的子类来处理不同的输出流类型,如`FileOutputStream、ByteArrayOutputStream等。
  3. OutputStream提供了几种不同的写入方法,如write(byte[])write(byte[], int, int)等,可以满足不同应用场景下的需求。

缺点:

  1. OutputStream是一个抽象类,不能直接使用,需要使用它的实现类。
  2. OutputStream只能一次写入一个字节或字节数组,不能直接写入其他类型的数据,如String、int等,需要转换成字节数组后再进行写入。

应用场景

  1. 文件读写:使用FileOutputStream将数据写入到文件中,使用FileInputStream将数据从文件中读取出来。
  2. 网络传输:使用网络编程时,可以使用OutputStream将数据输出到网络连接中,将数据传输给远程服务器。
  3. 内存缓存:使用ByteArrayOutputStream将数据写入到内存缓冲区中,可以提高数据的读写速度。

使用方法

创建OutputStream对象

  在Java中,OutputStream是一个抽象类,不能直接被实例化。因此,我们需要使用其子类来创建OutputStream对象。

  常用的OutputStream子类有FileOutputStreamByteArrayOutputStreamDataOutputStream等。下面以FileOutputStream为例,介绍如何创建OutputStream对象:

FileOutputStream outputStream = new FileOutputStream("./template/hello.txt");

  上述代码创建了一个名为./template/hello.txt的文件输出流,它将数据流写入到磁盘文件中。

使用OutputStream输出数据

  OutputStream提供了一系列方法,可以用于输出不同类型的数据到目标设备中。例如,可以使用write()方法将字节数组写入到磁盘文件中:

byte[] data = "Hello, OutputStream!".getBytes();
outputStream.write(data);

  除了write()方法,OutputStream还提供了很多其他方法,可以用于输出不同类型的数据。例如,write(byte[] b, int off, int len)方法可以将字节数组部分内容写入到磁盘文件中。

关闭OutputStream

  在使用OutputStream写入数据时,为了保证数据的完整性和可靠性,需要及时关闭OutputStream。可以使用close()方法关闭输出流对象:

outputStream.close();

源代码分析

在Java中,OutputStream是一个抽象类,包路径为:java.io.OutputStream

其源代码如下:

public abstract class OutputStream implements Closeable, Flushable {
    //...
    public abstract void write(int b) throws IOException;
    public void write(byte[] b) throws IOException {
        write(b, 0, b.length);
    }
    public void write(byte[] b, int off, int len) throws IOException {
        if ((off < 0) || (off > b.length) || (len < 0) ||
            ((off + len) > b.length) || ((off + len) < 0)) {
            throw new IndexOutOfBoundsException();
        } else if (len == 0) {
            return;
        }
        for (int i = 0 ; i < len ; i++) {
            write(b[off + i]);
        }
    }
    //...
}

  OutputStream 中有三个抽象方法未实现,write(int b)flush()close(),同时它还实现了 write(byte[] b)write(byte[] b, int off, int len) 这两个方法。

  • write(int b) 方法是用来向输出流中写入单个字节(b 的低 8 位)。它是一个抽象方法,需要被子类实现。

  • write(byte[] b) 方法是将 byte 数组 b 的所有字节写入到输出流中。它调用了 write(byte[] b, int off, int len) 方法,这个方法是将 byte 数组 b 中从偏移量 off 开始的 len 个字节写入输出流中。在实现这个方法的时候,它遍历了 byte 数组中的所有字节,并调用了 write(int b) 方法将每个字节写入输出流中。

  • flush() 方法用来将缓冲区中的数据写出到输出流中,这个方法是一个空实现方法,具体实现需要由子类实现。

  • close() 方法用来关闭输出流并释放与之相关的资源。这个方法同样是一个空实现方法,具体实现需要由子类实现。

其源码部分截图如下所示:

image.png

  总之,OutputStream 是所有输出流的基类,它定义了输出流的基本特性,并提供了一些常用的方法,如写入单个字节、写入字节数组等。任何继承自 OutputStream 的子类都需要实现它的抽象方法,以便正确地实现其功能。

测试用例

以下是一个简单的示例代码,演示了如何使用OutputStream将字符串写入到磁盘文件中:

测试用例代码

package com.example.javase.io.outputStream;

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

/**
 * @Author bug菌
 * @Date 2023-10-15 19:13
 */
public class OutputStreamTest {

    public static void main(String[] args) throws IOException {
        String str = "Hello, jym!";
        byte[] data = str.getBytes();
        OutputStream outputStream = null;

        try {
            outputStream = new FileOutputStream("./template/hello.txt");
            outputStream.write(data);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (outputStream != null) {
                outputStream.close();
            }
        }
    }
}

测试代码解析

  这是一个使用Java的输出流(OutputStream)将字符串输出到本地文件的例子。具体解析如下:

  1. 定义字符串
String str = "Hello, jym!";
  1. 将字符串转换为字节数组
byte[] data = str.getBytes();
  1. 创建输出流对象
OutputStream outputStream = null;
try {
    outputStream = new FileOutputStream("./template/hello.txt");
} catch (IOException e) {
    e.printStackTrace();
}

  这里使用了Java的文件输出流(FileOutputStream),将数据输出到本地文件。./template/hello.txt表示本地文件的路径,如果文件不存在则会创建文件。如果创建失败则会抛出IOException。

  1. 写入数据
outputStream.write(data);

  将字节数组写入输出流中。

  1. 关闭流
if (outputStream != null) {
    outputStream.close();
}

  为了防止资源泄漏,需要在使用完输出流后关闭它。这里使用了Java的异常处理机制,在代码中使用try-catch-finally语句块。

测试结果

根据测试用例执行结果如下:

image.png

小结

  本文详细介绍了Java中的OutputStream,包括它的作用、使用方法、源代码等内容。具体而言,本文介绍了OutputStream的概述和作用,以及如何创建OutputStream对象、使用OutputStream输出数据和关闭OutputStream等内容。

  同时,本文还给出了一个简单的演示代码和测试用例,帮助读者更好地掌握OutputStream的使用。

总结

  OutputStream是Java中最常用的输出流之一,它能够将数据流输出到目标设备中,例如磁盘文件、网络等。在使用OutputStream时,需要注意及时关闭输出流对象,避免数据的丢失或不完整。当需要将程序中生成的数据或结果输出到磁盘文件中时,可以使用OutputStream来完成。

附录源码

  如上涉及所有源码均已上传同步在「Gitee」,提供给同学们一对一参考学习,辅助你更迅速的掌握。

☀️建议/推荐你

  最后,如果这篇文章对你有所帮助,帮忙给作者来个一键三连,关注、点赞、收藏,您的支持就是我坚持写作最大的动力。

  同时欢迎大家关注公众号:「猿圈奇妙屋」 ,以便学习更多同类型的技术文章,免费白嫖最新BAT互联网公司面试题、4000G pdf电子书籍、简历模板、技术文章Markdown文档等海量资料。

📣关于我

我是bug菌,CSDN | 掘金 | infoQ | 51CTO 等社区博客专家,历届博客之星Top30,掘金年度人气作者Top40,51CTO年度博主Top12,华为云 | 阿里云| 腾讯云等社区优质创作者,全网粉丝合计15w+ ;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试题、4000G pdf电子书籍、简历模板等海量资料。


【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。