1 字符流
1.1 字符编码表
编码表就是字节(数字)和字符(汉字或者其他语言)的对应关系表。
ASCII: 1字节(0 + 7个二进制位) 128个字符
iso8859-1(latin) 1字节 256个字符。
gb2312(1980) 1/2 个字节 包含了六千多中文或者符号。
big5 1/2 个字节 支持繁体字。
gbk 1/2 字节 支持两万多的汉字以及字符。
unicode:国际标准码表。 可以表示任何国家的任何语言,并且任何字符都采用两个字节去存储。 unicode8.0 甚至支持emoji。
UTF-8:万国码
UTF-32: 采用4个字节去存储。
UTF-16:采用2/3/4个字节去存储。
UTF-8: 采用1/2/3/4个字节去存储。
只需要知道两个。
gbk: 中文在gbk中占2个字节。
utf-8: 中文在utf-8中占3个
文字--->(数字) :编码:就是看能看懂内容,转换成看不懂的内容。
(数字)--->文字 : 解码: 就是把看不懂的内容,转换成看懂的内容。
1.2 io分类回顾
2 转换流
2.1 转换流写入和读取的工作流程
2.2 OutputStreamWriter
OutputStreamWriter 是转换流。 是字符通向字节的桥梁。
可以指定编码集进行写入。
构造方法:
OutputStreamWriter(OutputStream out): 需要传递一个字节输出流。 采用默认编码方式进行写入。
OutputStreamWriter(OutputStream out, String charsetName): 第一个参数为字节输出流,第二个参数为编码集名称。 可以指定编码集进行写入。
写入方法。
写入方法,和之前字符流的写入方法是一样的。因为OutputStreamWriter属于字符流。
注意:
转换流本身并不具备读或者写的功能,它的作用是查询码表进行转码。
读或者写真正是由字节流做的
指定的编码集必须要存在,如果不存在就会报错
ANSI 在windows指的就是gbk。
2.3 OutputStreamReader
InputStreamReader 也是转换流。 字节通向字符的桥梁。
这个流可以指定编码进行读取。
构造方法:
InputStreamReader(InputStream in):传递一个字节输入流。 以默认编码方式进行读取。
InputStreamReader(InputStream in, String charsetName): 第一个是字节输入流。第二个是指定的编码方式。可以指定编码进行读取。
读取的方法:
通过转换流读取。 以字符为单位。 因为转换流属于字符流的一种。
注意:代码中是以字符为单位读的。但是内部会使用InputStream字节输入流,以字节为单位读取。
注意:
转换流本身并不具备读或者写的功能。它的作用查询码表进行转码。
数据其实真正是由字节流读或者写的。
文件是使用哪种编码存储,那么读取的时候就要指定哪种编码,否则就会出现乱码。
转换流作用:
可以指定编码集进行读写。
2.4 InputStreamReader
InputStreamReader 也是转换流。 字节通向字符的桥梁。
这个流可以指定编码进行读取。
构造方法
InputStreamReader(InputStream in):传递一个字节输入流。 以默认编码方式进行读取。
InputStreamReader(InputStream in, String charsetName): 第一个是字节输入流。第二个是指定的编码方式。可以指定编码进行读取。
读取的方法:
通过转换流读取。 以字符为单位。 因为转换流属于字符流的一种。
注意:代码中是以字符为单位读的。但是内部会使用InputStream字节输入流,以字节为单位读取。
注意:
转换流本身并不具备读或者写的功能。它的作用查询码表进行转码。
数据其实真正是由字节流读或者写的。
文件是使用哪种编码存储,那么读取的时候就要指定哪种编码,否则就会出现乱码。
转换流作用:
可以指定编码集进行读写。
2.4 转换流和子类的区别
字符流的继承体系。
字符输出流:
Writer: 是顶层父类。 是一个抽象类。
|-- OutputStreamWriter: 转换流,可以指定编码方式进行写入。
|-- FileWriter: 是以默认的编码方式进行写入。 是父类的一个更简单的用法。
字符输入流:
Reader: 顶层父类,是一个抽象类。
|-- InputStreamReader:转换流,可以指定编码进行读取。
|-- FileReader: 是以默认编码进行读取。 是父类更简单的写法。
总结:以下三种写法是一样的
使用转换流指定一个编码方式,这个指定的编码方式为gbk。
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("file03.txt"), "gbk");
使用转换流,不指定编码方式,会采用的默认的gbk。
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("file03.txt"));
使用子类FileWriter,采用的就是默认的gbk。
FileWriter fw = new FileWriter("file03.txt");
3 序列化流
3.1 ObjectOutputStream 序列化流
ObjectOutputStream 叫做序列化流,可以将java程序中的对象写入到文件中。
构造方法:
ObjectOutputStream(OutputStream out): 传递一个字节输出流对象。
其他方法:
void writeObject(Object obj):向文件中写入一个对象。
要写入的对象必须实现一个接口。这个接口叫做Serializable,如果没有实现这个接口,就会引发NotSerializableException
写入进去的内容我们是看不懂,因为它不是给我们看的。
3.2 ObjectInputStream 反序列化流
ObjectInputStream叫做反序列化流, 用来从文件中读取对象。
构造方法
ObjectInputStream(InputStream in): 传递一个字节输入流
读取对象的方法:
Object readObject(): 读取对象
注意:如果读取对象的时候,这个对象的class文件不存在,就会引发ClassNotFoundException。
如果想要写入多个对象,可以把这些对象放入到一个集合中,然后把集合写入到文件,最终再读取。
3.3 Serializable接口
Serializable 是序列化接口,一个类的对象想要被序列化,必须要实现这个接口。
这个接口中没有任何方法,它的作用只是做一个标记,实现这个接口的类的对象才能够被序列化。
3.4 注意
1. 被static修饰的成员,不会被序列化。
2. 如果希望某个对象的成员变量在序列化的时候不要写入到文件中,同时也不希望使用static。
可以使用另外一个关键字,这个关键字叫做transient。
transient 表示瞬态,被transient修饰的属性不会被序列化。
3.5 版本号冲突问题及解决方法
如果向文件中写入一个对象后,对这个对象所在的类进行修改,然后再读取就会引发异常。
原因是因为读取前和读取后的版本号(序列化)不一致
如何解决?
可以给这个类分配一个固定的版本号,这样这个类无论怎么修改,这个版本号都不会变。
如何给这个类分配一个固定的版本号?
直接在这个类中给出一个静态常量,叫做serialVersionUID。 这个静态常量表示的就是版本号(序列化)的意思
4 打印流
特点:
1. 只有输出,没有输入(只能写,不能读)
2. 使用比较方便。
PrintWriter(字符打印流):
构造方法:
PrintWriter(File file)
PrintWriter(OutputStream out)
PrintWriter(String fileName)
PrintWriter(Writer out)
PrintStream(字节打印流):
构造方法:
PrintStream(File file)
PrintStream(OutputStream out)
PrintStream(String fileName)
打印流里面写入的方法。
write: 如果写入的是数字,会查询ASCII码最终写入这个数字对应的字符。
print: 如果写入的是数字,会原样写入到文件中。写入之后不会换行。
println:写入之后会自动换行。
使用步骤:
1. 创建打印流对象
2. 调用方法,进行写入。
3. 释放资源
打印流的自动刷新
字符输出流写数据的时候需要刷新。
字节流写的时候不需要刷新
自动刷新的要求
1. 输出目标必须是流;
PrintWriter(OutputStream out, boolean autoFlush)
PrintWriter(Writer out, boolean autoFlush)
2. 第二的构造参数指定为true;
3. 必须调用println、printf或format之一才会生效。
5 Commons-IO 等第三方工具的使用
什么是第三方?
第一方: Oracle官方。
第二方: 程序员自己。
第三方: 除此之外全部都是第三方。
后期用的东西大多都是由第三方提供的工具。
这些工具都会以jar包的形式给你。
jar包就是一种压缩包。里面放的都是.class文件。
现在我们学的这个工具叫做commons-io,他也是第三方工具,也是也jar包的形式提供的,它对应的jar包是 commons-io-2.6.jar
commons-io 是由Apache(阿帕奇)提供的一个第三方工具,作用是简化了我们对IO流的操作。
Apache是 美国开源基金组织。
后期很多框架或者其他工具都是由apache维护或者提供的。
比如: tomcat。 active-mq。 struts2。 haddop,commons-io
如果要使用第三方工具,必须要进行导jar包。(重要)
步骤:
1. 在当前项目下新建文件夹,叫做lib
2. 把要导入的jar包拷贝到这个lib文件夹下。
3. 点击jar包 -> 右键 -> build path -> add to build path
在commons-io中,有一个工具类,可以完成很多功能,这个类叫做FileUtils
里面的方法
static void writeStringToFile(File file, String data):向文件中写入字符串。
static String readFileToString(File file):读取文件,并返回字符串。
static void copyFile(File srcFile, File destFile): 复制文件。srcFile源文件。destFile目标文件
static void copyDirectoryToDirectory(File srcDir, File destDir): 复制文件夹。
@Deprecated //这个东西叫做注解,这个注解的作用表示这个东西已经过时了,被用这个注解的方法,使用时方法就会被划上横线。
5.1 关联源码
按住Ctrl点方法,然后点Attach Source...,然后点External location,然后如果源码是以文件形式提供的就选External File,如果源码是以文件夹形式提供的,就选External Folder。
5 NIO介绍
BIO:同步阻塞IO
NIO:同步非阻塞IO。netty,dubbo
在指定IO操作的时候,可以去做其他事情。
NIO是基于 缓冲区, 通道,选择器。
AIO:异步非阻塞IO
阻塞指的是线程阻塞,线程在阻塞的时候就不能干其他事情了。
阻塞:看成去银行排队取钱,一直ATM前面排队。
非阻塞:去柜台拿个号,然后等着取钱,等着的时候,可以干别的。