IO简单的说就是程序和输入输出的各种相关的媒介的数据传输的一个通道。比如磁盘文件、控制台、网络等等。
IO分为输入流和输出流:
输入流:InputStream(8位字节流)和Reader(16位字符流)
输出流:OutputStream(8位字节流)和Writer(16位字符流)
图片来源与网络
InputStream、OutputStream、Reader、Writer,其实在我们的实际应用中,我们用到的一般是它们的子类,之所以设计这么多子类,目的就是让每一个类都负责不同的功能,以方便我们开发各种应用。
-----------------------------------------
java.io.InputStream的方法:
read( ) 读取一个字节,返回int类型。int 是一个字节,返回-1 已经读完了。
read( byte[ ] ) 参数为字节数组,数组有多长,就读取多长,具体还得看文件大小,如果返回-1 表示结束,否则返回读取的字节数长度。
read( byte[ ], int, int ) 第一个参数为字节数组,第二个参数是int类型,表示从数组的第几个下标开始存储,第三个参数也是int类型,表示存储多长。返回-1表示结束,否则返回读取的字节数长度。
readAllBytes( ) jdk9 的新方法,表示一口气全部读取上来,慎用。
skip ( long ) 跳过字节数
close( ) 关闭通道
-----------------------------------------
java.io.OutputStream的方法:
write (int ) 写一个字节 0~255
write(byte[]) 写一个数组
write(byte[], int, int) 写一个数组出去,你可以控制输出的数组位置,int起始位和int长度。
flush() 清理缓存,让她立即写出去
close 关闭通道
-----------------------------------------
FileInputStream 磁盘文件读取,是InputStream的子类。这里就不了说。
FileOutputStream 输出数据到磁盘,是OutputStream的子类,这里需要说的是,在linux系统输出时如果文件不存在会报错哦,所以先用File的 createNewFile( )方法先创建文件较为稳妥。
还有构造器出来可以传入String路径或者File路径封装对象以外,还可以传入一个boolean类型的参数。
这个boolean的类型是什么意思呢?
意思是是否开启追加模式?ture为开启,false为不开启,默认不开启。
如果不开启的话,如果你写入的文件已经存储并且里面有数据内容,她会直接覆盖掉原来的内容,可以这么理解:她会把文件的内容删除掉会写入她的东西。
如果开启追加模式,她就会在文件原有的内容后面继续写入,不会覆盖文件原有的数据内容。
-----------------------------------------
BufferedInputStream 是FileInputStream 的子类, 作用是在内存中继续缓存。
构造器是要传入一个InputStream类型参数。还可以指定缓冲区的大小,int类型的参数。
这是一个典型的装饰设计模式,他的任何子类都可以对一个继承自InputStream的原始流或其他链接流进行装饰,如我们常用的使用BufferedInputStream对FileInputStream进行装饰,使普通的文件输入流具备了内存缓存的功能,通过内存缓冲减少磁盘io次数。
BufferedOutputStream 同理也是继承与FileOutputStream,原理一样。
看到大牛的一遍文章写的比较详细→BufferedInputStream 用法
-----------------------------------------
ObjectInputStream 对象序列化流
特点:用于操作对象。可以将对象写入到文件中。
当一个对象要能被序列化,这个对象所属的类必须实现Serializable接口。否则会发生异常NotSerializableException异常。
public class Test implements Serializable {
}
ObjectOutputStream 对象序列化流
特点:用于操作对象。可以从文件中读取对象。
-----------------------------------------
序列化说明:
当一个对象要能被序列化,这个对象所属的类必须实现Serializable接口。否则会发生异常NotSerializableException异常。
同时当反序列化对象时,如果对象所属的class文件在序列化之后进行的修改,那么进行反序列化也会发生异常InvalidClassException。发生这个异常的原因如下:
该类的序列版本号与从流中读取的类描述符的版本号不匹配
该类包含未知数据类型
该类没有可访问的无参数构造方法
Serializable标记接口。该接口给需要序列化的类,提供了一个序列版本号。serialVersionUID. 该版本号的目的在于验证序列化的对象和对应类是否版本匹配。
public class Test implements Serializable {
//给类显示声明一个序列版本号。
private static final long serialVersionUID = 123456L;
private String name;
private int age;
public Test() {
super();
}
public Test(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Test [name=" + name + ", age=" + age + "]";
}
}
瞬态关键字transient
当一个类的对象需要被序列化时,某些属性不需要被序列化,这时不需要序列化的属性可以使用关键字transient修饰。只要被transient修饰了,序列化时这个属性就不会琲序列化了。同时静态修饰也不会被序列化,因为序列化是把对象数据进行持久化存储,而静态的属于类加载时的数据,不会被序列化。
public class Test implements Serializable {
//给类显示声明一个序列版本号。
private static final long serialVersionUID = 1L;
private static String name;
//transient 关键字
private transient int age;
public Test() {
super();
}
public Test(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Test [name=" + name + ", age=" + age + "]";
}
}
-----------------------------------------
打印流
打印流添加输出数据的功能,使它们能够方便地打印各种数据值表示形式.
打印流根据流的分类:
字节打印流 PrintStream
字符打印流 PrintWriter
方法:
void print(String str): 输出任意类型的数据,
void println(String str): 输出任意类型的数据,自动写入换行操作
/*
* 需求:把指定的数据,写入到printFile.txt文件中
*
* 分析:
* 1 创建流
* 2 写数据
* 3 关闭流
*/
public class PrintWriterDemo {
public static void main(String[] args) throws IOException {
//创建流
//PrintWriter out = new PrintWriter(new FileWriter("printFile.txt"));
PrintWriter out = new PrintWriter("printFile.txt");
//2,写数据
for (int i=0; i<5; i++) {
out.println("helloWorld");
}
//3,关闭流
out.close();
}
}
可以通过构造方法,完成文件数据的自动刷新功能
构造方法:
开启文件自动刷新写入功能
public PrintWriter(OutputStream out, boolean autoFlush)
public PrintWriter(Writer out, boolean autoFlush)
/*
* 分析:
* 1 创建流
* 2 写数据
*/
public class PrintWriterDemo2 {
public static void main(String[] args) throws IOException {
//创建流
PrintWriter out = new PrintWriter(new FileWriter("printFile.txt"), true);
//2,写数据
for (int i=0; i<5; i++) {
out.println("helloWorld");
}
//3,关闭流
out.close();
}
}