Java从入门到入土|[Java] 神秘的IO流 (上)

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

阅读指南
  • 前言
  • Java的I/O处理方式
    • 1.1 I/O的基本原理
    • 1.2 可用的流工具类
    • 1.3 输入流
    • 1.4 输出流
  • 以字节为数据单位的流类
    • 2.1 InputStream类
    • 2.2 OutputStream类
  • 以字符为数据单位的流类
    • 3.1 Reader类
    • 3.2 Writer类

前言 Java 的 I/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类的方法的简单介绍。
返回类型 方法 描述
int available() 返回当前输入流的数据读取方法可以读取的有效字节数量
int read() 从当前数据流中读取一个字节,若已经到达流结尾,则返回 -1
int read(byte[] bytes) 从当前输入流读取一定的 byte 数据,并存放在数组中,然后返回读取的 byte 数据的数量,若已经到达流结尾,则返回 -1
int read(byte[] bytes, int off, int len) 从当前输入流读取一定的 byte 数据,并存放在数组中指定位置,然后返回读取的 byte 数据的数量,若已经到达流结尾,则返回 -1
void reset() 将当前输入流重新定位到最后一次调用 mark() 方法时的位置
void mark(int readlimit) 在当前输入流中做标记位置,当调用 reset() 方法时将返回到该位置,从标记位置开始,到再读入 readlimit 个字符为止,这个标记都维持有效
boolean markSupported() 测试当前输入流是否支持 mark() 和 reset() 方法,只要其中一个不支持,则返回 false
long skip(long n) 跳过和丢弃当前输入流中的 n 个字节数据
void close() 关闭当前输入流,并释放任何与之关联的系统资源
下面我们通过一个实例来介绍如何使用 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(); } } }

该实例的运行结果如下:
Java从入门到入土|[Java] 神秘的IO流 (上)
文章图片

2.2 OutputStream类 OutputStream 类是字节输出流的抽象类,定义了输出流的各种操作方法。
下面是 OutputStream 类的方法的简单介绍。
返回类型 方法名称 说明
void write(byte[] b) 将 byte[] 数组中的数据写入到当前输出流
void write(byte[] b, int off, int len) 将 byte[] 数组下标 off 开始的 len 长度的数据写入到当前输出流
abstract void write(int b) 写入一个 byte 数据到当前输出流
void flush() 刷新当前输出流,并强制写人所有缓冲的字节数据
void close() 关闭当前输出流,并释放所有与当前输出流有关的系统资源
下面我们通过一个实例来了解如何使用 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(); } } }

该实例的运行结果如下:
Java从入门到入土|[Java] 神秘的IO流 (上)
文章图片

以字符为数据单位的流类 前面我们介绍了字节流输入和输出的基本方法,并且用实例分别演示了从控制台获取字符串和向控制台输出字符串。在这两个实例中,所使用的字符串都需要转换成字节数组,然后以字节为单位进行输入和输出。
如果只是进行简单的字符操作,使用 Reader 和 Writer 实现字符流的读取和写入将更加方便和快捷。
字符流用于处理字符数据的读取和写入,它以字符(char)为单位。Reader 类和 Writer 类是字符流的抽象类,它们定义了字符流读取和写入的基本方法,各个子类会依其特点实现或覆盖这些方法。
在 Java 语言中,字符类型的数据是双字节的,而计算机中每个汉字的显示也需要占用两个字节,所以 Java 的字符类型可以容纳汉字信息。
3.1 Reader类 Reader 类是字符输入流的抽象类,其中定义了操作字符输入流的各种方法。
Reader 类的方法的说明如下表所示。
返回类型 方法名称 说明
boolean ready() 判断此数据流是否准备好
int read() 读入一个字符,若已读到流结尾,则返回值为 -1
int read(char[]) 读取一些字符到 char[] 数组内,并返回所读入的字符的数量,若已到达流结尾,则返回 -1
abstract int read(char[] chars, int off, int len) 读取一些字符到 char[] 数组下标 off 开始到 off+len 的位置,并返回所读入的字符的数量。若已到达流结尾,则返回 -1
void reset() 将当前输入流重新定位到最后一次调用 mark() 方法时的位置
void mark(int readLimit) 在当前输人流中做标记位置,当调用 reset() 方法时,将返回到该位置。从标记位置开始,到再读入 readLimit 个字符为止,这个标记都维持有效
boolean markSupported() 测试当前输入流是否支持 mark() 和 reset() 方法,只要有一个方法不支持,就返回 false
long skip(long n) 跳过参数 n 指定的字符数量,返回所跳过字符的数量
abstract void close() 关闭该流并释放与之关联的所有资源。在关闭该流后,再调用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(); } } }

该实例的运行结果如下:
Java从入门到入土|[Java] 神秘的IO流 (上)
文章图片

3.2 Writer类 Writer 类是用于解决字符输出流的类,它的地位和作用与 Reader 类在输入流的地位和作用是相同的,也是所有字符输出流的超类。
Writer类的主要方法如下表所示。
返回类型 方法名称 说明
void write(char[ ] c) 将字符数组的数据写入到字符输出流
abstract void write(char[] c, int off, int len) 将字符数组从下标 off 开始向输出流写入 len 长度的数据
void write(int c) 向输出流写人一个字符数据
void write(String str) 向输出流写人一个字符串数据
void write(String str, int off, int len) 向输出流写入一个字符串,从 off 开始,长度为 len 的数据
abstract void flush() 刷新当前输出流,并强制写入所有缓冲区的字节数据
abstract void close() 向输出流写入缓冲区的数据,然后关闭当前输出流,并释放所有与当前输出流有关的系统资源
下面我们通过一个实例来了解如何使用 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(); } } }

该实例的运行结果如下:
Java从入门到入土|[Java] 神秘的IO流 (上)
文章图片

?
【Java从入门到入土|[Java] 神秘的IO流 (上)】
这次的分享就到这里啦,继续加油哦^^
?下期预告:IO 流的处理方式及其对文件和文件夹的操作
有出错的地方欢迎在评论区指出来,共同进步,谢谢啦

    推荐阅读