持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第19天,点击查看活动详情
转换流概述
- 转换流(处理流的一种)提供了在字节流和字符流之间的转换 Java API提供了两个转换流: ➢InputStreamReader: 将InputStream转换为Reader ➢OutputStreamWriter: 将Writer转 换OutputStream
- 字节流中的数据都是字符时,转成字符流操作更高效。
- 很多时候我们使用转换流来处理文件乱码问题。实现编码和 解码的功能。
编码:字符数组、字符串 ---> 字节、字节数组 解码:字节、字节数组 --->字符数组、字符串
字符集
编码表的由来:计算机只能识别二进制数据,早期由来是电信号。为了方便应用计算机,让它可以识别各个国家的文字。就将各个国家的文字用数字来表示,并一一对应,形成一张表。这就是编码表。
常见的编码表
- ASCII:美国标准信息交换码。用一个字节的7位可以表示。
- ISO8859-1:拉丁码表。欧洲码表。用一个字节的8位表示。
- GB2312:中国的中文编码表。最多两个字节编码所有字符
- GBK:中国的中文编码表升级,融合了更多的中文文字符号。最多两个字节编码
- Unicode:国际标准码,融合了目前人类使用的所有字符。为每个字符分配唯一的字符码。所有的文字都用两个字节来表示。
- UTF-8:变长的编码方式,可用1-4个字节来表示一个字符。(在标准UTF-8编码中, 超出基本多语言范围( BMP-Basic Multilingual Plane )的字符被编码为4字节格式,但是在修正的UTF-8编码中,他们由代理编码对( surrogatepairs )表示,然后这些代理编码对在序列中分别重新编码。结果标准UTF-8编码中需要4个字节的字符,在修正后的UTF-8编码中将需要6个字节。)
补充(字符编码)
●Unicode不完美,这里就有三个问题,一个是,我们已经知道,英文字母只用一个字节表示就够了;第二个问题是如何才能区别Unicode和ASCII;计算机怎么知道两个字节表示一个符号,而不是分别表示两个符号呢?第三个,如果和GBK等双字节编码方式一样,用最高位是1或0表示两个字节和一个字节, 就少了很多值无法用于表示字符,不够表示所有字符。所以Unicode在很长一段时间内无法推广,直到互联网的出现。 ●面向传输的众多UTF (UCS Transfer Format)标准出现了,顾名思义,UTF-8就是每次8个位传输数据,而UTF-16就是每次16个位。这是为传输而设计的编码,并使编码无国界,这样就可以显示全世界上所有文化的字符了。 ● Unicode只 是定义了一个庞大的、全球通用的字符集,并为每个字符规定了唯一确定的编号,具体存储成什么样的字节流,取决于字符编码方案。 推荐的Unicode编码是UTF-8和UTF-16。
ANSI:美国国家标准学会( AMERICAN NATIONAL STANDARDS INSTITUTE: ANSI )
其他流
标准输入输出流
●System.in和System.out分别代表了系统标准的输入和输出设备;默认输入设备是:键盘,输出设备是:显示器 ●System.in的类型是InputStream ●System.out的类型是PrintStream,其是OutputStream的子类,FilterOutputStream的子类 ●重定向:通过System类的setIn, setOut方 法对默认设备进行改变。 ➢public static void setln(InputStream in) ➢public static void setOut(PrintStream out)
打印流
打印流:PrintStream 和PrintWriter
提供了一系列重载的print() 和 println()
数据流
DataInputStream 和 DataOutputStream
作用:用于读取或写出基本数据类型的变量或字符串
练习:将内存中的字符串、基本数据类型的变量写出到文件中。
注意:处理异常的话,仍然应该使用try-catch-finally.
将文件中存储的基本数据类型变量和字符串读取到内存中,保存在变量中。 注意点:读取不同类型的数据的顺序要与当初写入文件时,保存的数据的顺序一致!
对象流
●ObjectInputStream 和OjbectOutputSteam ➢用于存储和读取基本数据类型数据或对象的处理流。它的强大之处就是可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。 ●序列化:用ObjectOutputStream类保存基本类型数据或对象的机制 ●反序列化: 用ObjectInputStream类读取基本类型数据或对象的机制 ●ObjectOutputStream 和ObjectInputStream不能序列化static和transient修饰的成员变量
对象的序列化
●对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。// 当其它程序获取了这种二进制流,就可以恢复成原来的Java对象 ●序列化的好处在于可将任何实现了Serializable接口的对象转化为字节数据,使其在保存和传输时可被还原 ●序列化是RMI (Remote Method Invoke-远程方法调用)过程的参数和返回值都必须实现的机制,而RMI是JavaEE的基础。因此序列化机制是JavaEE平台的基础 ●如果需要让某个对象支持序列化机制,则必须让对象所属的类及其属性是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一。否则,会抛出NotSerializableException异常
Serializable ➢Externalizable
总结
序列化过程:将内存中的java对象保存到磁盘中或通过网络传输出去;使用ObjectOutputStream实现 反序列化:将磁盘文件中的对象还原为内存中的一个java对象;使用ObjectInputStream来实现
自定义类实现序列化与反序列化操作
自定义类(比如Person)需要满足如下的要求,方可序列化
- 1.需要实现接口:Serializable
- 2.当前类提供一个全局常量:serialVersionUID
- 3.除了当前Person类需要实现Serializable接口之外,还必须保证其内部所有属性也必须是可序列化的。(默认情况下,基本数据类型可序列化)
- 补充:ObjectOutputStream和ObjectInputStream不能序列化static和transient修饰的成员变量
serialVersionUID的理解
RandomAccessFile(随机存取文件流)
我们可以用RandomAccessFile这个类,来实现一个多线程断点下载的功能,用过下载工具的朋友们都知道,下载前都会建立两个临时文件,一个是与被下载文件大小相同的空文件,另一个是记录文件指针的位置文件,每次暂停的时候,都会保存上一次的指针,然后断点下载的时候,会继续从上一次的地方下载,从而实现断点下载或上传的功能,有兴趣的朋友们可以
自己实现下。
NIO
Java NIO概述
NIO2
Path、Paths和Files核心API
Path接口
Files类