[Java] 神秘的IO流 (上)

🔥一个人走得远了,就会忘记自己为了什么而出发,希望你可以不忘初心,不要随波逐流,一直走下去🎶
🦋 欢迎关注🖱点赞👍收藏🌟留言🐾
🦄 本文由 程序喵正在路上 原创,CSDN首发!
💖 系列专栏:Java入门
🌠 首发时间:2022年7月7日
✅ 如果觉得博主的文章还不错的话,希望小伙伴们三连支持一下哦

🔥前言

JavaI/O 处理技术可以将数据保存到文本文件中、二进制文件甚至是 ZIP 文件中,以达到永久保存数据的要求。

🔥Java的I/O处理方式

Java 的输入输出功能来自 java.io 包的 InputStream 类、OutputStream 类、Reader 类和 Writer 类,以及继承它们的各种子类。这些类以流的形式处理数据。

流是一组有序的数据序列,根据操作的类型,分为输入流和输出流两种,程序从输入流读取数据,向输出流写入数据。

Java 是纯面向对象的程序语言,每一个数据流都是一个对象,它们提供了各种支持 “读入” 与 “写出” 操作的流类,比如 FileInputStream 类和 FileOutputStream 类。

1.1 I/O的基本原理

Java 通过数据流处理数据的输入和输出。输入模式由程序创建某个信息来源的数据流并打开该数据流获取指定信息来源的数据,这些数据来源可以是文件、网络、压缩包或者其他数据源。

与输入模式相反,输出模式由程序创建某个输出对象的数据流并打开该数据对象(即输出目标)将数据写入数据流。数据流对象会将数据存储到相应的目标中。这些输出目标可以是文件、网络、压缩包、控制台或其他数据输出目标。

1.2 可用的流工具类

Java 语言定义了许多类专门负责各种方式的输入和输出,这些类都被放在 java.io 包中。其中,所有输入流类都是抽象类 InputStream(字节输入流)和抽象类 Reader(字符输入流)的子类,而所有输出流都是抽象类 OutputStream(字节输出流)和抽象类 Writer(字符输出流)的子类。

1.3 输入流

InputStream 类是字节输入流的抽象类,是所有字节输入流的父类。该类中所有方法遇到错误时都会引发 IOException 异常。

下面是对该类中的一些方法的简单介绍。

方法描述
read()从输入流中读取数据的下一个字节,返回 0~255 范围内的 int 字节值。如果因为已经到达流末尾而没有可用的字节,则返回值为 -1
read(byte[] b)从输入流中读入一定长度的字节,并以整数的形式返回字节数
mark(int readlimit)在输入流的当前位置放置一个标记,readlimit 参数告知此输入流在标记位置失效之前允许读取的字节数
reset()将输入指针返回到当前所做的标记处
skip(long n)跳过输入流上的n个字节并返回实际跳过的字节数
markSupported()如果当前流支持 mark()/reset() 操作,就返回 true
close()关闭此输入流并释放与该流关联的所有系统资源

注意:并不是所有的 InputStream 类的子类都支持 InputStream 中定义的所有方法(如skip()mark()、**reset()**等),这些方法只对某些子类有用。

Java 中的字符是 Unicode 编码,是双字节的。InputStream 是用来处理字节的,在处理字符文本时不是很方便。Java 为字符文本的输入单独提供了一套专门的类 Reader,但 Reader 类并不能代替 InputStream 类,只是在处理字符串时简化了编程。Reader 类是字符输入流的抽象类,所有字符输入流的实现都是它的子类。

Reader 类中的方法与 InputStream 中的方法类似。

1.4 输出流

OutputStream 类是字节输出流的抽象类,此抽象类是表示输出字节流的所有类的超类。

OutputStream 类中的所有方法均返回 void,在遇到错误时会引发 IOException 异常。

下面对 OutputStream 类中的方法做简单的介绍。

方法描述
write(int b)将指定的字节写入此输出流
write(byte[] b)b.length 个字节从指定的 byte 数组写入此输出流
write(byte[] b, int off , int len)将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流
flush()彻底完成输出并清空缓存区
close()关闭输出流

Writer 类是字符输出流的抽象类,所有字符输出类的实现都是它的子类。

🔥以字节为数据单位的流类

字节流用于处理二进制数据的读取和写入,它以字节(byte)为单位。InputStream 类和 OutputStream 类是字节流的抽象类,它们定义了数据流读取和写入的基本方法,各个子类会依其特点实现或覆盖这些方法。

2.1 InputStream类

InputStream 类是字节输入流的抽象类,定义了操作输入流的各种方法。

下面是InputStream类的方法的简单介绍。

返回类型方法描述
intavailable()返回当前输入流的数据读取方法可以读取的有效字节数量
intread()从当前数据流中读取一个字节,若已经到达流结尾,则返回 -1
intread(byte[] bytes)从当前输入流读取一定的 byte 数据,并存放在数组中,然后返回读取的 byte 数据的数量,若已经到达流结尾,则返回 -1
intread(byte[] bytes, int off, int len)从当前输入流读取一定的 byte 数据,并存放在数组中指定位置,然后返回读取的 byte 数据的数量,若已经到达流结尾,则返回 -1
voidreset()将当前输入流重新定位到最后一次调用 mark() 方法时的位置
voidmark(int readlimit)在当前输入流中做标记位置,当调用 reset() 方法时将返回到该位置,从标记位置开始,到再读入 readlimit 个字符为止,这个标记都维持有效
booleanmarkSupported()测试当前输入流是否支持 mark()reset() 方法,只要其中一个不支持,则返回 false
longskip(long n)跳过和丢弃当前输入流中的 n 个字节数据
voidclose()关闭当前输入流,并释放任何与之关联的系统资源

下面我们通过一个实例来介绍如何使用 InputStream 类从控制台获取用户输入的字符串信息。

创建 InputStreamGetStr 类,在类中创建 InputStream 类的实例对象 is,并为其赋值为 System 类的 in 属性,该类表示控制台输入流,从 is 输入流中获取一些字节信息,用这些字节信息创建一个字符串,并输出到控制台中。

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

public class InputStreamGetStr {
    public static void main(String[] args) {

        //创建InputStream类的对象,获取控制台的输入流
        System.out.println("请输入内容:");
        InputStream is = System.in;

        try {
            //从输入流读取数据到字节数组
            byte[] bs = new byte[50];
            int i = is.read(bs);

            System.out.println("控制台输入的内容是:" + new String(bs).trim());

            //关闭输入流
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

该实例的运行结果如下:
在这里插入图片描述

2.2 OutputStream类

OutputStream 类是字节输出流的抽象类,定义了输出流的各种操作方法。

下面是 OutputStream 类的方法的简单介绍。

返回类型方法名称说明
voidwrite(byte[] b)byte[] 数组中的数据写入到当前输出流
voidwrite(byte[] b, int off, int len)byte[] 数组下标 off 开始的 len 长度的数据写入到当前输出流
abstract voidwrite(int b)写入一个 byte 数据到当前输出流
voidflush()刷新当前输出流,并强制写人所有缓冲的字节数据
voidclose()关闭当前输出流,并释放所有与当前输出流有关的系统资源

下面我们通过一个实例来了解如何使用 OutputStream 类向控制台输出字符串信息。

创建 OutputStreamWriteStr 类,在类中创建 OutputStream 类的实例对象 out,并为其赋值为 System 类的 out 属性,该属性是控制台的输出流,再定义一个字节数组,该数组包含将要输出到控制台的字符串信息,并通过 out 对象在控制台输出该字节数组的内容。

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

public class OutputStreamWriteStr {
    public static void main(String[] args) {
        //获取控制台的输出流
        OutputStream out = System.out;

        try {
            //将字节数组内容写入输出流
            byte[] bs = "使用OutputStream输入流在控制台输出字符串\n".getBytes();
            out.write(bs);

            bs = "输出内容:\n".getBytes();
            out.write(bs);

            bs = "\t程序喵正在路上".getBytes();
            out.write(bs);

            //关闭输出流
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

该实例的运行结果如下:

🔥以字符为数据单位的流类

前面我们介绍了字节流输入和输出的基本方法,并且用实例分别演示了从控制台获取字符串和向控制台输出字符串。在这两个实例中,所使用的字符串都需要转换成字节数组,然后以字节为单位进行输入和输出。

如果只是进行简单的字符操作,使用 ReaderWriter 实现字符流的读取和写入将更加方便和快捷。

字符流用于处理字符数据的读取和写入,它以字符(char)为单位。Reader 类和 Writer 类是字符流的抽象类,它们定义了字符流读取和写入的基本方法,各个子类会依其特点实现或覆盖这些方法。

Java 语言中,字符类型的数据是双字节的,而计算机中每个汉字的显示也需要占用两个字节,所以 Java 的字符类型可以容纳汉字信息。

3.1 Reader类

Reader 类是字符输入流的抽象类,其中定义了操作字符输入流的各种方法。

Reader 类的方法的说明如下表所示。

返回类型方法名称说明
booleanready()判断此数据流是否准备好
intread()读入一个字符,若已读到流结尾,则返回值为 -1
intread(char[])读取一些字符到 char[] 数组内,并返回所读入的字符的数量,若已到达流结尾,则返回 -1
abstract intread(char[] chars, int off, int len)读取一些字符到 char[] 数组下标 off 开始到 off+len 的位置,并返回所读入的字符的数量。若已到达流结尾,则返回 -1
voidreset()将当前输入流重新定位到最后一次调用 mark() 方法时的位置
voidmark(int readLimit)在当前输人流中做标记位置,当调用 reset() 方法时,将返回到该位置。从标记位置开始,到再读入 readLimit 个字符为止,这个标记都维持有效
booleanmarkSupported()测试当前输入流是否支持 mark()reset() 方法,只要有一个方法不支持,就返回 false
longskip(long n)跳过参数 n 指定的字符数量,返回所跳过字符的数量
abstract voidclose()关闭该流并释放与之关联的所有资源。在关闭该流后,再调用read()ready()mark()reset()skip() 方法就会抛出异常

下面我们通过一个实例来了解如何使用 Reader 类的子类 InputStreamReader 实现从控制台获取用户输入的字符串信息。

首先,创建 ReaderStr 类,在类中创建 InputStreamReader 类的实例对象 isr,并将其初始化为控制台的字符输入流,从 isr 字符输入流中获取一些字符信息到字符数组中,用来给字符数组创建一个字符串,并输出到控制台中。

import java.io.IOException;
import java.io.InputStreamReader;

public class ReaderStr {
    public static void main(String[] args) {

        //获取控制台输入流
        System.out.println("请输入内容:");
        InputStreamReader isr = new InputStreamReader(System.in);

        try {
            //从控制台读取输入内容
            char[] cs = new char[50];
            isr.read(cs);

            //将获取到的内容输出到控制台
            String str = new String(cs);
            System.out.println("输入的内容是:" + str.trim());

            //关闭输入流
            isr.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

该实例的运行结果如下:
在这里插入图片描述

3.2 Writer类

Writer 类是用于解决字符输出流的类,它的地位和作用与 Reader 类在输入流的地位和作用是相同的,也是所有字符输出流的超类。

Writer类的主要方法如下表所示。

返回类型方法名称说明
voidwrite(char[ ] c)将字符数组的数据写入到字符输出流
abstract voidwrite(char[] c, int off, int len)将字符数组从下标 off 开始向输出流写入 len 长度的数据
voidwrite(int c)向输出流写人一个字符数据
voidwrite(String str)向输出流写人一个字符串数据
voidwrite(String str, int off, int len)向输出流写入一个字符串,从 off 开始,长度为 len 的数据
abstract voidflush()刷新当前输出流,并强制写入所有缓冲区的字节数据
abstract voidclose()向输出流写入缓冲区的数据,然后关闭当前输出流,并释放所有与当前输出流有关的系统资源

下面我们通过一个实例来了解如何使用 Writer 类的子类 PrintWriter 实现向控制台输出字符串信息的功能。

首先,创建 WriterStr 类,在类中创建 PrintWriter 类的实例对象 out,并将其初始化为控制台的字符输出流,再定义一个字符数组,该数组包含要输出到控制台的字符串信息,并通过 out 对象在控制台输出该字符数组的内容。

import java.io.*;

public class WriteStr {
    public static void main(String[] args) {

        //获取控制台输出流
        Writer out = new PrintWriter(System.out);

        try{
            //将字符数组中的数据输出到控制台
            char[] cs = "Writer\n".toCharArray();
            out.write(cs);

            cs = "输出内容:\n".toCharArray();
            out.write(cs);

            cs = "\t程序喵正在路上".toCharArray();
            out.write(cs);

            //刷新输出流的缓冲区,将数据输出
            out.flush();

            //关闭输出流
            out.close();
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}

该实例的运行结果如下:

在这里插入图片描述
🧸这次的分享就到这里啦,继续加油哦^^
✨下期预告:IO 流的处理方式及其对文件和文件夹的操作
🍭有出错的地方欢迎在评论区指出来,共同进步,谢谢啦

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序喵正在路上

你的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值