博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

java相关的流

Posted on 2020-08-30 20:46  kali98k  阅读(98)  评论(0编辑  收藏  举报

一、缓冲流

11.简介

能够高效读写的缓冲流,能够 转换编码的转换流,能够持久化存储对象的序列化流等等。这些功能更为强大的流,都是在基本的流对象基础之上 创建的相当于是对基本流对象的一种增强。

 

1.2. 概述

缓冲流,也叫高效流,是对4个基本的 FileXxx 流的增强,所以也是4个流,按照数据类型分类:

字节缓冲流 BufferedInputStream BufferedOutputStream

字符缓冲流 BufferedReader BufferedWriter

缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO 次数,从而提高读写的效率。

1.3 字节缓冲流

构造方法public BufferedInputStream(InputStream in) :创建一个 新的缓冲输入流。

public BufferedOutputStream(OutputStream out) 创建一个新的缓冲输出流。

构造举例,代码如下:

// 创建字节缓冲输入流

BufferedInputStream bis = new BufferedInputStream(new FileInputStream("bis.txt"));

// 创建字节缓冲输出流

BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("bos.txt")

作用:文件读写快

 

1.4 字符缓冲流

构造方法

public BufferedReader(Reader in) :创建一个 新的缓冲输入流。

public BufferedWriter(Writer out) 创建一个新的缓冲输出流。

// 创建字符缓冲输入流

BufferedReader br = new BufferedReader(new FileReader("br.txt"));

// 创建字符缓冲输出流

BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));

特有方法

字符缓冲流的基本方法与普通字符流调用方式一致,不再阐述,我们来看它们具备的特有方法。

BufffferedReader public String readLine() : 读一行文字。

BufffferedWriter public void newLine() : 写一行行分隔符,由系统属性定义符号。

 

二、 转换流

2.1 字符编码和字符集

字符编码

计算机中储存的信息都是用二进制数表示的,而我们在屏幕上看到的数字、英文、标点符号、汉字等字符是二进制 数转换之后的结果。

按照某种规则,将字符存储到计算机中,称为编码

反之,将存储在计算机中的二进制数按照 某种规则解析显示出来,称为解码

比如说,按照A规则存储,同样按照A规则解析,那么就能显示正确的文本符 号。反之,按照A规则存储,再按照B规则解析,就会导致乱码现象。

字符编码 Character Encoding : 就是一套自然语言的字符与二进制数之间的对应规则

字符集

字符集 Charset :也叫编码表。是一个系统支持的所有字符的集合,包括各国家文字、标点符号、图形符 号、数字等。

计算机要准确的存储和识别各种字符集符号,需要进行字符编码,一套字符集必然至少有一套字符编码。常见字符 集有ASCII字符集、GBK字符集、Unicode字符集等。

 

 

 

 

可见,当指定了编码,它所对应的字符集自然就指定了,所以编码才是我们最终要关心的。

ASCII字符集

ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁 字母的一套电脑编码系统,用于显示现代英语,主要包括控制字符(回车键、退格、换行键等)和可显 示字符(英文大小写字符、阿拉伯数字和西文符号)。

基本的ASCII字符集,使用7位(bits)表示一个字符,共128字符。ASCII的扩展字符集使用8位(bits 表示一个字符,共256字符,方便支持欧洲常用字符。

ISO-8859-1字符集

拉丁码表,别名Latin-1,用于显示欧洲使用的语言,包括荷兰、丹麦、德语、意大利语、西班牙语等。 ISO-5559-1使用单字节编码,兼容ASCII编码。

GBxxx字符集

GB就是国标的意思,是为了显示中文而设计的一套字符集。

GB2312:简体中文码表。一个小于127的字符的意义与原来相同。但两个大于127的字符连在一起时, 就表示一个汉字,这样大约可以组合了包含7000多个简体汉字,此外数学符号、罗马希腊的字母、日文 的假名们都编进去了,连在ASCII里本来就有的数字、标点、字母都统统重新编了两个字节长的编码,这 就是常说的"全角"字符,而原来在127号以下的那些就叫"半角"字符了。

GBK:最常用的中文码表。是在GB2312标准基础上的扩展规范,使用了双字节编码方案,共收录了 21003个汉字,完全兼容GB2312标准,同时支持繁体汉字以及日韩汉字等。

GB18030:最新的中文码表。收录汉字70244个,采用多字节编码,每个字可以由1个、2个或4个字节 组成。支持中国国内少数民族的文字,同时支持繁体汉字以及日韩汉字等。

Unicode字符集

Unicode编码系统为表达任意语言的任意字符而设计,是业界的一种标准,也称为统一码、标准万国 码。它最多使用4个字节的数字来表达每个字母、符号,或者文字。有三种编码方案,UTF-8、UTF-16和UTF- 32。最为常用的UTF-8编码。

UTF-8编码,可以用来表示Unicode标准中任何字符,它是电子邮件、网页及其他存储或传送文字的应用 中,优先采用的编码。互联网工程工作小组(IETF)要求所有互联网协议都必须支持UTF-8编码。所以, 我们开发Web应用,也要使用UTF-8编码。它使用一至四个字节为每个字符编码,编码规则:

1. 128个US-ASCII字符,只需一个字节编码。

2. 拉丁文等字符,需要二个字节编码。

3. 大部分常用字(含中文),使用三个字节编码。

4. 其他极少使用的Unicode辅助字符,使用四字节编码。

 

 

2.2 InputStreamReader

 

转换流 java.io.InputStreamReader ,是Reader的子类,是从字节流到字符流的桥梁。它读取字节,并使用指定 的字符集将其解码为字符。它的字符集可以由名称指定,也可以接受平台的默认字符集。

构造方法

InputStreamReader(InputStream in) : 创建一个使用默认字符集的字符流。

InputStreamReader(InputStream in, String charsetName) : 创建一个指定字符集的字符流。

InputStreamReader isr = new InputStreamReader(new FileInputStream("in.txt"));

InputStreamReader isr2 = new InputStreamReader(new FileInputStream("in.txt") , "GBK");

2.3 OutputStreamWriter

转换流 java.io.OutputStreamWriter ,是Writer的子类,是从字符流到字节流的桥梁。使用指定的字符集将字符

编码为字节。它的字符集可以由名称指定,也可以接受平台的默认字符集。

构造方法

OutputStreamWriter(OutputStream in) : 创建一个使用默认字符集的字符流。

OutputStreamWriter(OutputStream in, String charsetName) : 创建一个指定字符集的字符流

OutputStreamWriter isr = new OutputStreamWriter(new FileOutputStream("out.txt"));

OutputStreamWriter isr2 = new OutputStreamWriter(new FileOutputStream("out.txt") , "GBK");

 

 

 

2.4 作用

编码的转换

三、 序列化

3.1 概述

Java 提供了一种对象序列化的机制。用一个字节序列可以表示一个对象,该字节序列包含该 对象的数据 对象的 类型 对象中存储的属性 等信息。

字节序列写出到文件之后,相当于文件中持久保存了一个对象的信息。

 反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化

 对象的数据 对象的类型 对象中 存储的数据 信息,都可以用来在内存中创建对象。看图理解序列化:

 

3.2 ObjectOutputStream

java.io.ObjectOutputStream 类,将Java对象的原始数据类型写出到文件,实现对象的持久存储。

构造方法

public ObjectOutputStream(OutputStream out) 创建一个指定OutputStream的ObjectOutputStream

 

FileOutputStream fileOut = new FileOutputStream("employee.txt");

ObjectOutputStream out = new ObjectOutputStream(fileOut);

序列化操作

1. 一个对象要想序列化,必须满足两个条件:

该类必须实现 java.io.Serializable 接口, Serializable 是一个标记接口,不实现此接口的类将不会使任 何状态序列化或反序列化,会抛出 NotSerializableException

该类的所有属性必须是可序列化的。如果有一个属性不需要可序列化的,则该属性必须注明是瞬态的,使用 transient 关键字修饰。

 

3.3 ObjectInputStream

ObjectInputStream反序列化流,将之前使用ObjectOutputStream序列化的原始数据恢复为对象。

构造方法

public ObjectInputStream(InputStream in) 创建一个指定InputStream的ObjectInputStream。

反序列化操作1

如果能找到一个对象的class文件,我们可以进行反序列化操作,调用 ObjectInputStream 读取对象的方法:

public final Object readObject () : 读取一个对象

对于JVM可以反序列化对象,它必须是能够找到class文件的类。如果找不到该类的class文件,则抛出一个 ClassNotFoundException 异常

 

另外,当JVM反序列化对象时,能找到class文件,但是class文件在序列化对象之后发生了修改,那么反序列化操 作也会失败,抛出一个 InvalidClassException 异常。发生这个异常的原因如下:

该类的序列版本号与从流中读取的类描述符的版本号不匹配

该类包含未知数据类型

该类没有可访问的无参数构造方法

Serializable 接口给需要序列化的类,提供了一个序列版本号。 serialVersionUID 该版本号的目的在于验证序 列化的对象和对应类是否版本匹配

3.4 什么时候使用序列化

当对象保存到物理介质的时候,比如对象保存到磁盘、文件
当对象在网络上传输的时候,比如通过套接字传输对象,netty
当对象远程过程调用的时候,比如通过RMI调用对象

 

四、 打印流

4.1 概述

平时我们在控制台打印输出,是调用 print 方法和 println 方法完成的,这两个方法都来自于

java.io.PrintStream 类,该类能够方便地打印各种数据类型的值,是一种便捷的输出方式。

 

 

4.2 PrintStream

构造方法

public PrintStream(String fileName) 使用指定的文件名创建一个新的打印流。

PrintStream ps = new PrintStream("ps.txt")

 

改变打印流向

System.out 就是 PrintStream 类型的,只不过它的流向是系统规定的,打印在控制台上。不过,既然是流对象, 我们就可以玩一个"小把戏",改变它的流向。

public class PrintDemo {

public static void main(String[] args) throws IOException {

// 调用系统的打印流,控制台直接输出97

System.out.println(97);

// 创建打印流,指定文件的名称

PrintStream ps = new PrintStream("ps.txt");

// 设置系统的打印流流向,输出到ps.txt

System.setOut(ps);

// 调用系统的打印流,ps.txt中输出97

System.out.println(97);

}

}