I/O流学习笔记及梳理

常见I/O流的梳理

引言:对于I/O,新手会用但不知道原理,平时看代码就看的很痛苦,一用就要去查。
eg:

File file = new File("xxx");

OutputStream outputStream = new FileOutputStream(file);

这个还好,这两个呢?

Writer out = new OutputStreamWriter(new FileOutputStream(new File("xxx")));
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));

反正笔者是看的很头疼,所以写来梳理常见的I/O流及用法

tip:这种一次套用多个方法属于代码链,建议掌握;因为虽然能拆分代码,但很繁琐(看别人代码也多数是代码链)

字节流和字符流

  1. 字节流 :InputStream , OutputStream
  2. 字节流 :Writer , Reader

首先很重要的概念,上述的都是抽象类,这也是为什么每次都需要通过子类来创建对象的原因(常见的就是FileXxx)

File file = new File("xxx");

OutputStream outputStream = new FileOutputStream(file);

上文中的代码现在也就能理解了

区别
数据传输中都是使用字节数据,而程序中往往使用的是字符数据类型。
而最大的区别就是字符流使用了缓冲区,对于字符输出流需要显式调用flush() ,才能输出数据(或者字符流关闭时强制刷新)

关联
转换流,为了解决两种流的转换,就应运而生。

转换流

OutputStreamWriter , InputStreamReader
以下是源码片段:

public class OutputStreamWriter extends Writer{

public OutputStreamWriter(OutputStream out)
}
public class InputStreamReader extends Reader{

public InputStreamReader(InputStream in)
}

即:转换流都是对应字符流的子类
而且可以通过构造方法接收对应字节流的类实例
即:
xxxStreamXxxer的转换器接收的其实是xxxStream的具体子类

eg:

File file = new File("xxx");

FileOutputStream fileOutputStream =  new FileOutputStream(file);

Writer out = new OutputStreamWriter(fileOutputStream);

等价于开始的代码:

Writer out = new OutputStreamWriter(new FileOutputStream(new File("xxx")));

现在是不是就理解一点了?

打印流

输出数据时,OutputStream只允许输出字节数据,而Writer只允许输出字符数据和字符串数据。而其它类型的数据(整数,浮点数等)怎么办呢?为了简化输出,打印流就被设计出来了。

打印流类 : PrintStream , PrintWriter
(关于两者的区别,笔者也不太懂,就不班门弄斧了。)

那既然是为了简化输出,那理所当然的,两者的构造方法都能接受包括File 、OutputStream、Writer

而最重要的一些方法:
public void print(数据类型 变量)
public void println(数据类型 变量)

也被重载多次,能输出任意类型的数据。

System类对I/O的支持

趁热打铁,看到上面的print,println,有没有一点熟悉的感觉?

System.out.println();
常量类型描述
public static final PrintStream err常量错误输出
public static final PrintStream out常量系统输出
public static final InputStream in常量系统输入

没错,System.out 其实就是PrintStream类, 然后调用println()的方法

所以System.out.println() 实际上就是利用了I/O操作的输出

而System.in是InputStream,即输入字节流,但正如前文所说,对中文的处理不够好,所以就需要包装成别的流,常见的就是借助BufferedReader 缓冲输入流

缓冲流Bufferxxx

包含:BufferedInputStream,BufferedOutputStream,BuffredRead,BufferedWriter

此处只讲
BufferedReader 缓冲输入流
提供了一种字符流的缓冲区数据读取,进行数据读取时,会将读取到的数据暂时保存在缓冲区中,然后可以将内容一次性取出.

public class BufferedReader extends Reader {

public BufferedReader(Reader in)

public String readLine() throws IOException {
}
}

如源码所示,该类定义的构造方法只能接受Reader的实例

而对System.in常见的处理之一就是:
先使用转换流:InputStreamReader把System.in变为字符流,再用BufferReader包装起来

InputStream inputStream = System.in;

Reader reader = new InputStreamReader(inputStream);

BufferedReader input = new BufferedReader(reader);

就等价于开头的最后一个代码

BufferedReader input = new BufferedReader(new InputStreamReader(System.in));

之后就可以利用**BufferReader提供的readLine()**接受输入信息
eg:

BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
String msg = input.readLine();
System.out.println(msg);

(键盘输入:原来如此)
执行结果:
原来如此

Scanner输入流工具

对于System.in相信各位用得更多的还是

Scanner scanner = new Scanner(System.in);

Scanner,如其名,是专门的输入数据类,构造方法中可以接受File、InputStream、Readable(Reader实现的接口之一)类型的输入实例。

除了完成输入数据操作外,也可以很方便地对输入数据进行验证。此处不展开讲,不过建议读者好好学习一下,很实用的一个工具类。

结语

本文并没有对I/O流的各种类,如内存操作流、管道流等说明,也没有引入相关的UML图跟各个类的常用方法,后续可能会补出一篇相关的内容。

因为本文主要用于梳理常用流的关系跟包装关系等,鉴于笔者的水平也不够,可能有错误,欢迎大家指出

第一次写博客,谢谢大家,希望多多包涵

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值