1. Io流
流是一组有序的、有起点和终点的字节集合,是对数据传输的总称和抽象。即数据在两设备之间的传输称为流,流的本质是数据传输,数据传输是需要通道的,而IO流就是数据传输的通道。
分类
根据处理数据类型的不同分为字节流和字符流。
根据数据流向的不同分为输入流和输出流。
字符流
InputStream和OutputStream是java中可以按照最小字节单位读取的流,即每次读写一个字节,字节流是直接连接到输入源的流。
**字节输入流InputStream**InputStream是所有输入字节流的父类,是一个抽象类。
- ByteArrayInputStream、StringBufferInputStream、FileInputStream 是三种基本的介质流,它们分别从Byte 数组、StringBuffer、和本地文件中读取数据
- PipedInputStream是从与其它线程共用的管道中读取数据
ObjectInputStream 和所有FilterInputStream 的子类都是装饰流(装饰器模式的主角)
字节输出流OutputStream
OutputStream 是所有的输出字节流的父类,它是一个抽象类。
ByteArrayOutputStream、FileOutputStream 是两种基本的介质流,它们分别向Byte 数组、和本地文件中写入数据
- PipedOutputStream 是向与其它线程共用的管道中写入数据
- ObjectOutputStream 和所有FilterOutputStream 的子类都是装饰流
字符流
字符流是以字符为单位进行数据处理的IO流。本质其实就是基于字节流读取时,去查找指定的码表。是以Reader和Writer为基础派生的一系列类。
**字符输入流Reader**
Reader 是所有的输入字符流的父类,它是一个抽象类。
- CharReader、StringReader 是两种基本的介质流,它们从Char 数组、String中读取数据
- PipedReader 是从与其它线程共用的管道中读取数据
- BufferedReader 是一个装饰器,它和其子类负责装饰其它Reader 对象。FilterReader 是所有自定义具体装饰流的父类,其子类PushbackReader 对Reader 对象进行装饰,会增加一个行号
InputStreamReader 是一个连接字节流和字符流的桥梁,它将字节流转变为字符流
字符输出流Writer
Writer 是所有的输出字符流的父类,它是一个抽象类。
CharArrayWriter、StringWriter 是两种基本的介质流,它们分别向Char 数组、String 中写入数据
- PipedWriter 是向与其它线程共用的管道中写入数据
- BufferedWriter 是一个装饰器为Writer 提供缓冲功能
- PrintWriter 和PrintStream 功能和使用极其类似
- OutputStreamWriter 是OutputStream 到Writer 转换的桥梁
字符流和字节流的区别
- 字节流以字节(8bit)为单位,字符流以字符为单位
- 字节流能处理所有类型的数据(如图片、.avi等),字符流只能处理纯文本的数据
结论:如果处理纯文本的数据优先考虑字符流,其他情况用字节流。
字符流与字节流转换
InputStreamReader:字节到字符的桥梁
OutputStreamWriter:字符到字节的桥梁
2. File
Files.exists():检测文件路径是否存在。
Files.createFile():创建文件。
Files.createDirectory():创建文件夹。
Files.delete():删除一个文件或目录。
Files.copy():复制文件。
Files.move():移动文件。
Files.size():查看文件个数。
Files.read():读取文件。
Files.write():写入文件。
3. 序列化与反序列
序列化
Java对象转换为字节序列的过程称为对象的序列化,即将对象写入到IO流中。
序列化是为了解决在对象流进行读写操作时所引发的问题。序列化机制允许将实现序列化的Java对象转换位字节序列,这些字节序列可以保存在磁盘上,或通过网络传输,以达到以后恢复成原来的对象。序列化机制使得对象可以脱离程序的运行而独立存在。
要对一个对象序列化,这个对象就需实现Serializable接口。序列化只能保存对象的非静态成员变量,而不能保存任何成员方法和静态成员变量,并且保存的只是变量的值,变量的修饰符对序列化没有影响。
序列化
- 创建 ObjectOutputStream
- 调用ObjectOutputStream对象的writeObject ()得到序列化对象
package com.lymn.io;
import java.io.*;
public class Person implements Serializable {
private int age;
private char sex;
private String name;
public Person(int age, char sex, String name) {
this.age = age;
this.sex = sex;
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
", sex=" + sex +
", name='" + name + '\'' +
'}';
}
public static void main(String[] args) throws IOException {
Person p=new Person(22,'男',"小红");
ObjectOutputStream out=new ObjectOutputStream(new FileOutputStream("D:/ca/person.txt"));
out.writeObject(p);
}
}
sr com.lymn.io.Person匓猴蛅a I ageC sexL namet Ljava/lang/String;xp u7t 灏忕孩
任何用 transient 关键字标明的成员变量,都不会被保存(保密数据、Thread对象或流对象)
反序列化
反序列化就是从 IO 流中恢复对象。
反序列化
- 创建 ObjectInputStream
- 调用ObjectInputStream对象的readObject()得到序列化对象
package com.lymn.io;
import java.io.*;
public class Person implements Serializable {
private int age;
private char sex;
private String name;
public Person(int age, char sex, String name) {
this.age = age;
this.sex = sex;
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
", sex=" + sex +
", name='" + name + '\'' +
'}';
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectInputStream out=new ObjectInputStream(new FileInputStream ("D:/ca/person.txt"));
Person p= (Person) out.readObject();
System.out.println(p.toString());
}
}
Person{age=22, sex=男, name=’小红’}
序列化版本号serialVersionUID
java序列化提供了一个private static final long serialVersionUID 的序列化版本号,版本号相同,即使更改了序列化属性,对象也能正确被反序列化回来。
反序列化使用的class版本号与序列化使用的不一致,会报InvalidClassException异常。
序列化版本号可自由指定,如果不指定,JVM会根据类信息自己计算一个版本号,这样随着class的升级,就无法正确反序列化,不利于jvm间的移植,可能class文件没有更改,但不同jvm可能计算的规则不一样,这样也会导致无法反序列化。
使用场景
- 需要网络传输的对象都需要实现序列化接口
- 对象的类名、实例变量(包括基本类型,数组,对其他对象的引用)都会被序列化;方法、类变量、transient实例变量都不会被序列化
- 某个变量不被序列化,使用transient修饰
- 序列化对象的引用类型成员变量,也必须是可序列化的
- 反序列化时必须有序列化对象的class文件
- 通过文件、网络读取序列化后的对象时,必须按照实际写入的顺序读取
- 单例类序列化,需要重写readResolve()方法;否则会破坏单例原则
- 同一对象序列化多次,第一次序列化为二进制流,以后都只是保存序列化编号,不会重复序列化
- 建议所有可序列化的类加上serialVersionUID 版本号,方便项目升级
4.流体系图
5.BIO、NIO、AIO
BIO:Block IO 同步阻塞式 IO,数据的读取写入必须阻塞在一个线程内等待其完成。模式简单使用方便,并发处理能力低。
NIO: 同步非阻塞 IO,在Java 1.4 中引入了NIO框架,对应 java.nio 包,提供了 Channel , Selector,Buffer等抽象。客户端和服务器端通过 Channel(通道)通讯,实现了多路复用。对于高负载、高并发的(网络)应用,应使用 NIO 的非阻塞模式来开发
AIO:Asynchronous IO 是 NIO 的升级,也叫 NIO2。在 Java 7 中引入,实现了异步非堵塞 IO ,异步 IO 的操作基于事件和回调机制,即应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。
