目录
1.IO:Input/Output
4.java.io.FileInputStream
5.java.io.FileOutputStream
6.java.io.BufferedReader
10.java.io.File类
11.对象流ObjectInputStream、ObjectOutputStream
通过IO完成对硬盘文件的读/写。
2.IO流的分类:
①根据流的方向进行分类(以内存为参照物):
往内存中去,叫做输入Input,也叫做读Read
从内存中出来,叫做Output,也叫做写Write
②按照读取数据方式不同进行分类:
a.按照字节的方式读取数据,一次读取1个字节byte,等同于一次读取8个二进制位,这
种流是万能的,什么类型的文件都可以读取。包括:文本文件、图片、音频、视频。
b.按照字符的方式读取数据,一次读取一个字符,这种流是为了方便读取普通文本文件
而存在的,这种流不能读取图片、音频、视频等文件,只能读取纯文本文件,连word
文件都无法读取。
③综上所述流分为输入流/输出流、字节流/字符流。
3.java中所有的流都在java.io.*下。
java IO流中的四大类(这四个都是抽象类):
java.io.InputStream:字节输入流
java.io.OutPutStream:字节输出流
java.io.Reader:字符输入流
java.io.Writer:字符输出流
注意:在java中只要类名以"Stream"结尾的都是字节流;以"Reader/Writer"结尾的都是字符流。
所有的流都实现了java.io.Closeable接口,都是可关闭的,都有close()方法。流是一个内存和硬盘之间的通道,用完之后一定要关闭,不然会耗费很多资源。
所有的输出流都实现了java.io.Flushable接口,都是可刷新的,都有flush()方法。输出流在最终输出之后,一定要计得flush()刷新一下,这个刷新表示将通道/管道当中剩余未输出的数据强行输出完,刷新的作用就是清空管道。如果没有flush(),可能会导致丢失数据。
主要掌握的流:
①文件专属:
java.io.FileInputStream
java.io.FileOutputStream
java.io.FileReader
java.io.FileWriter
②转换流(将字节流转换为字符流):
java.io.InputStreamReader
java.io.OutputStreamWriter
③缓冲流专属:
java.io.BufferedReader
java.io.BufferedWriter
java.io.BufferedInputStream
java.io.BufferedOutputStream
④数据流专属:
java.io.DataInputStream
java.io.DataOutputStream
⑤标准输出流:
java.io.PrintWriter
java.io.PrintStream
⑥对象专属流:
java.io.ObjectInputStream
java.io.ObjectOutputStream
IO流继承结构图:
①文件字节输入流,万能的,任何类型的文件都可以采用这个流来读取。
②字节的方式,完成输入、读的操作(硬盘--->内存)。
③创建文件输入流对象,完成对文件的读。在finally语句块当中确保流一定关闭,并且只有当
流不为空时需要关闭,当流为null时不需要进行关闭。
利用循环读出文件中的数据,read()方法一次读取一个字节,这样做的话内存硬盘之间交互
次数过多,效率低,因此也可以使用read(byte[] bytes)方法实现一次读取多个字节。
④FileInputStream类的其他常用方法:
int available():返回流当中剩余的没有读到的字节数量。
long skip(long n):跳过几个字节不读。
①文件字节流输出,负责写,从内存到硬盘。
②对象创建。当文件不存在时,会自动创建该文件。
注意:这种构造方法会将原文件清空,然后重新写入谨慎使用。构造方法中有第二个参数
boolean append,将该参数设置为true即可实现以追加的方式在文件末尾写入。
③在文件中利用byte[]数组写入数据。
①带有缓冲区的字符输入流。使用这个流的时候不需要自定义char数组,也不需要自定义byte
数组,自带缓冲。
②该类的构造方法中是传入一个Reader。
当一个流的构造方法中需要一个流的时候,这个被传进来的流叫做节点流,外部负责包装的
这个流叫做包装流/处理流。比如当前程序中,FileReader是一个节点流,BufferedReader是
包装流/处理流。
对于包装流来说,只需要关闭最外层流即可,里面的节点流会自动关闭。
③有一个方法readline(),一次可以读一行。
读完之后会返回一个null,因此可以利用其作为循环结束条件。
7.对于java.io.DataInputStream和java.io.DataOutputStream流来说,右DataOutputStream写的文件,只能使用DataInputStream去读,并且读的时候需要提前知道写入的顺序,读的顺序需要和写的顺序一致,才可以正常取出数据。
8.java.io.PrintStream/java.io.PrintWriter:标准的字节/字符输出流,默认输出到控制台上。标准输出流不需要手动close()关闭。
9.关于IO流的使用主要还是要参考帮助文档,此处也只是简单描述一些常用使用方式。
①File与之前所说的流四大类没有关系,不能完成文件的读和写。
②File对象代表文件和目录路径名的抽象表示形式。一个File对象有可能对于的是目录,也可
能是文件。
③参考帮助文档掌握File类中常用的方法。
①序列化和反序列化。
②序列化对象。
如果要想自定义类型可以序列化,需要将自定义类型实现接口Serializable,否则会出现异
常java.io.NotSerializableException。
通过查看源代码,发现Serializable接口只是一个标志接口,这个接口中什么代码都没有,
只起到标识、标志的作用,java虚拟机看到这个类实现了这个接口,可能会对这个类进行特
殊待遇:java虚拟机看到这个接口之后,如果自定义类中没有手动写出序列化版本号,虚拟
机会为该类默认自动生成一个序列化版本号。
public interface Serializable{
}
③反序列化对象。
④如果需要一次序列化多个对象,可以将对象放到集合当中,序列化集合。并且参与序列化
的集合如ArrayList以及集合中的元素都需要实现java.io.Serializable接口。
⑤transient关键字:表示游离的,不参与序列化。
⑥java语言中是采用什么机制来区分类的?
a.首先通过类名进行比对,如果类名不一样,肯定不是同一个类;
b.如果类名一样,再靠序列化版本号进行区分。
因此如果由java虚拟机来自动生成序列化版本号有什么缺陷?
一旦代码确定编译生成序列化版本号之后,就不能进行后续的修改,因为只要修改,必
然会重新编译,此时会生成新的序列化版本号,这个时候java虚拟机就会认为这是一个全
新的类。
最终结论:凡是一个类实现了Serializable接口,建议给该类提供一个固定不变的序列化版
本号。这样即使以后这个类的代码修改了,但是版本号不变,java虚拟机会认为是同一个
类。
12.IO + Properties类的联合使用。
①有一个文件,文件中的数据如下:
②将该文件中的数据加载到Properties对象当中。
③一个很好的设计理念:以后经常需要改变的数据,可以单独写到一个文件中,使用程序动
态读取,以后只需要修改这个文件的内容,java代码不需要改动,不需要重新编译,服务器
也不需要重启,就可以拿到动态的信息。(以后在JDBC的学习中会使用到)
类似于以上机制的这种文件被称为配置文件。并且当配置文件中的内容格式是:
key1=value
key2=value
此时把配置文件称为属性配置文件,java规范中要求属性配置文件建议以.properies结尾。
而Properties是专门存放属性配置文件的一个类。在属性配置文件中#表示注释。属性配置文
件中如果key重复的话,value会自动覆盖。"="两边不要有空格。也可以用":"隔开(但是这种
方式不建议使用)。
PS:根据动力节点课程整理,如有侵权,联系删除。