JAVA学习10——流的编码、序列化、打印流

1.流的编码

字符编码:就是一套自然语言的字符域二进制数之间的对应规则。编码表(字符集):生活中文字和计算机中二进制的对应规则。

常见字符集有ASCII字符集(ASCII编码)、GBK字符集(GBK编码、最常用的中文码表)、Unicode字符集(UTF8编码、UTF16编码、UTF32编码)。UTF8时电子邮件、网页以及其他存储或传送文字的应用中、有限采用的编码。
在这里插入图片描述

1.1字符通向字节的桥梁——OutputStreamWriter/InputStreamReader

OutputStreamWriter可以使用指定的charset将要写入流中的字符编码成字节。

java.io.OutputStreamWriter extends Writer
构造方法:
	OutputStreamWriter(OutputStream out) 创建使用默认字符编码的OutputStreamWriter
	OutputStreamWriter(OutputStream out, String charsetName)
	参数:
		String charsertName:指定编码表名称,不区分大小写, 可以是utf-8、bgk等,不指定默认使用UTF-8

使用步骤:
1.创建OutputStreamWriter对象,构造方法中传递字节输出流和指定的编码表名称。
2.使用OutputStreamWriter对象中的方法write,把字符转换为字节存储缓冲区中(编码)
3.使用Output’StreamWriter对象中的方法flush,把内存缓冲区中的字节刷新到文件中(使用字节流写字节的过程)
4.释放资源。

OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("C:\\a.txt","utf-8");
osw.write("你好");
ows.flush();
osw.close();

InputStreamReader,是字节刘翔字符流的桥梁,使用指定的charset读取字节并为其解码为字符。

构造方法
	InputStreamReader(InputStream in)
	InputStreamReader(InputStream in, Stream charsetName)

使用步骤:
1.创建InputStreamReader对象,构造方法中传递字节输入流和指定字节编码表名称;
2.使用InputStreamReader对象,构造方法中传递字节输入流和指定的编码表名称;
3.释放资源
注意:构造方法中指定的编码表名称要和文件的编码相同,否则乱码。

InputStreamReader isr = new InputStreamReader(new FileInputStream,"UTF-8");
int len = 0;
while((len = isr.read())!=-1) {
	System.out.println(len);
}
isr.close();释放资源

1.2 综合练习——转换文件编码

步骤:
1.创建InputStreamReader对象,构造方法中传递字节输入流和指定的编码表名称GBK;
2.创建OutputStreamWriter对象,构造方法中传递字节输出流和指定的编码表名称UTF-8;
3.使用InputStreamReader对象中的方法read读取文件;
4.使用OutputStreamWriter对象中的方法write,把读取的数据写入到文件中。
5.释放资源;

2.序列化

把对象以流的方式,写入到文件中保存,叫写对象,也叫对象的序列化,writeObejct§;把文件中保存的对象,以流的方式读取出来,叫做读对象,也就对象的反序列化。
Object obj = new Person(“Lucy”,10);

2.1对象的序列化流

java.io.ObjectOutputStream extends OutputStream(OutputStream out)

特有成员方法:
	void writeObject(Object obj) 将指定的对象写入ObjectOutputStream

注意:要进行序列化和反序列化的类必须实现Serializable接口,就会给类添加一个标记(标记型接口,即接口中无任何方法) ,当我们进行序列化和反序列化的时候,就会检测类上是否有这个标记。有的化就可以序列化和反序列化;没有的话就会抛出一个NotSerializableException异常。

使用步骤:
0.先对要进行写入/写出的对象的类,实现序列化接口;
1.创建ObejctOutputStream对象,构造方法中传递字节输出流;
2.使用ObjectOutputStream对象中的方法writeObject,把对象写入到文件中;
3.释放资源;

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("C:\\a.txt");
oss.writeObject(new Person("Lucy",22));
oss.close();

2.2对象的反序列化流

java.io.ObjectInputStream extends  InputStream
构造方法:
	ObjectInputStream(InputStream in)
特有成员方法:
	Object readObject() 从ObjectInputStream读取对象;

使用步骤:
1.创建ObjectInputStream对象,构造方法中传递字节输入流;
2.使用ObjectInputStream对象中的方法readObject读取保存对象的文件。
3.释放资源;
4.使用读取出来的对象;

反序列化过程中两个常见异常:
(1)readObject方法声明抛出了ClassNotFoundException(class文件找不到异常)。当不存在对象的class文件时抛出异常。
(2)当JVM反序列化对象时,能找到class文件,但class文件在序列化对象后发生修改,那么反序列化操作也会失败,抛出一个InvalidClassException异常。发生这个异常原因常常有三个:该类的序列版本号与从流中读取的类描述的版本号不匹配;该类包含未知数据类型;该类没有可访问的无参数构造方法。

在这里插入图片描述
即解决方法是,Person实现类添加了Serializable接口后,在Person实现类中添加:

private static final long serialVersionUID = -234L;//静态、final、long

因此,反序列化也有两个前提:
1.类必须实现Serializable;
2.必须存在类对应的class文件;

2.3瞬态关键字

static关键字:静态关键字
	今天太优先于非静态加载到内存中(静态优先于对象进入到内存中)。被static修饰的成员变量不能被序列化。

transient关键字:瞬态关键字
	被transient修饰成员变量,不能被序列化,但没有static的性质。

2.4 序列化集合——案例

/*
序列化集合
	当我们想在文件中保存多个对象时,可以把多个对象存储到一个集合中,对集合进行序列化和反序列化;
步骤:
	1.定义一个存储Person对象的ArrayList集合;
	2.往ArrayList集合中存储Person对象;
	3.创建一个序列化流ObjectOutputStream对象;
	4.使用ObjectOutputStream对象中的方法writeObject,对集合进行序列化;
	5.创建一个反序列化ObjectinputStream对象;
	6.使用反序列化对象方法readObject读取文件中保存的集合;
	7.把Object类型的集合转换为ArrayList类型;
	8.遍历ArrayList集合
	9.释放资源;
*/

ArrayList<Person> list = new ArrayList<>();
list.add(new Person("Lucy",22));
list.add(new Person("nancy",23));
//省略。。。。。。
Object o = ois.readObject();
ArrayList<Person> list2 = (ArrayList<Person>)o;//强转
for(Person p : list2) {
	System.out.println();
}

3.打印流

为其他输出流添加功能,使它们能够方便打印各种数据值。例如System.out就是一个打印流。

java.io.PrintStream: 打印流
PrintStream特点:
	1.只负责数据输出,不负责数据的读取;
	2.与其他输出流不同,PrintStream永远不会抛出IOException;
	3.有特有的方法:
		void print(任意类型值)
		void println(任意类型值,并换行)
	
构造方法:
	PrintStream(File file):输出的目的地是一个文件
	PrintStream(OutputStream out):输出的目的地是一个字节输出流
	PrintStream(String fileName)输出的目的地是一个文件路径
PrintStream extends OutputStream 因此继承父类的成员方法。

注意:
	如果使用继承父类的write方法写数据,那么查看数据时候会自动查询编码表;如果使用自己特有的方法print/println方法写数据,写数据会原样输出(97就是97,a就是a)。

打印流的流向,是可以被改变的。

可以改变输出语句的目的地,输出语句默认在控制台进行输出。
使用System.setOut方法改变输出语句的目的地,改编为参数中传递的打印目的地
static void setOut(PrintStream out)

例子
PrintStream ps = new PrintStream("D:\\a.txt");
System.setOut(ps);
System.out.println("我打印流的目的地是a.txt");
ps.close();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值