day22【Properties、ResourceBundle工具类、缓冲流、转换流、序列化】课上
1.属性集(掌握,很重要)
概念介绍
1.Properties,属于双列集合,他的父类Hashtable,jdk1.0就存在了。
2.该集合没有泛型,因为该集合中的存放数据类型都是String类型
3.可以将该集合的数据存储到持久设备上(了解),也可以将持久设备上的数据加载到内存中(很重要)
4.Properties可以将持久设备上的数据加载到内存中,主要是加载和当前项目有关配置文件中的内容
配置文件:就是一个文件(文本文件),存放一些key=value的数据,这些数据都是关于当前项目的一些信息。
有关加载数据库信息 有关配置框架信息,并且配置文件中的数据没有汉字。
特有方法
package com.itheima.sh.properties_01;import java.util.Properties;
import java.util.Set;/*构造方法:Properties() 创建一个无默认值的空属性列表。Properties属性集的特有方法:1.Object setProperty(String key, String value) 调用 Hashtable 的方法 put。添加数据2.String getProperty(String key) 用指定的键在此属性列表中搜索属性。 相当于 value get(key)方法根据键获取值3.Set<String> stringPropertyNames() 获取所有的键 相当于 keySet*/
public class PropertiesDemo01 {public static void main(String[] args) {//1.创建集合对象 Properties() 创建一个无默认值的空属性列表。Properties p = new Properties();//2.添加数据p.setProperty("张杰", "谢娜");p.setProperty("汪峰", "章子怡");p.setProperty("邓超", "孙俪");p.setProperty("张杰", "柳岩");//3.获取所有键Set<String> keys = p.stringPropertyNames();//4.取出每个键for (String key : keys) {//获取值String value = p.getProperty(key);System.out.println(key+"---"+value);}}
}
小结:
1.Object setProperty(String key, String value) 调用 Hashtable 的方法 put。添加数据
2.String getProperty(String key) 用指定的键在此属性列表中搜索属性。 相当于 value get(key)方法
根据键获取值
3.Set stringPropertyNames() 获取所有的键 相当于 keySet
使用Properties集合读取配置文件(开发使用)
1.使用该集合读取的配置文件要求如下:
1)必须以key=value形式存在
2)不要在配置文件中书写分号
3)配置文件存在的位置可以任意,可以放到项目根目录,还可以放到src位置(后期都放在src位置)
4)不建议书写中文,但是可以书写
5)不要书写双引号,因为配置文件中的数据都是字符串
2.代码演示:
配置文件:
username=root
password=1234
package com.itheima.sh.properties_01;import java.io.FileInputStream;
import java.io.FileReader;
import java.util.Properties;
import java.util.Set;/*使用Properties集合读取配置文件使用方法:1.void load(InputStream inStream) 从输入流中读取属性列表(键和元素对)。2.void load(Reader reader) 按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。说明:1.上述加载方法执行完毕之后配置文件中的数据就会被加载到属性集对象中*/
public class PropertiesDemo02 {public static void main(String[] args) throws Exception{//1.创建属性集对象Properties p = new Properties();//2.使用对象调用加载方法加载配置文件的数据
// FileInputStream fis = new FileInputStream("person.properties");//上述加载方法执行完毕之后配置文件中的数据就会被加载到属性集对象中//1.void load(InputStream inStream) 从输入流中读取属性列表(键和元素对)。
// p.load(fis);//2.void load(Reader reader) 按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。p.load(new FileReader("person.properties"));//3.遍历集合pSet<String> keys = p.stringPropertyNames();for (String key : keys) {System.out.println("键:"+key);System.out.println("值:"+p.getProperty(key));}}
}
小结:
1.使用属性集Properties中的加载方法可以加载配置文件中的数据:
1.void load(InputStream inStream) 从输入流中读取属性列表(键和元素对)。如果配置文件中有汉字不能使用,会出现乱码2.void load(Reader reader) 按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。
2.配置文件的后缀名不一定是.properties
3.上述加载方法执行完毕之后配置文件中的数据就会被加载到属性集对象中
4.可以将该集合的数据存储到持久设备上(了解):
void store(OutputStream out, String comments) 将集合中的数据长久保存到持久设备上参数:out:关联要写的文件的路径comments:表示配置文件的说明即注释,不要写中文。配置文件中的注释使用 # 表示
2.ResourceBundle工具类(掌握)
作用:专门用来加载当前项目以.properties 结尾的配置文件。
属于抽象类,不能创建对象,我们需要使用该工具类中的静态方法获取子类(PropertyResourceBundle )对象
static ResourceBundle getBundle(String baseName) 根据指定的配置文件名获取ResourceBundle类的对象,不需要给后缀名举例:假设配置文件整体名字是:person.properties 这里只需给person 即可
根据配置文件中的key获取value:
String getString(String key)
使用该工具类ResourceBundle读取的配置文件要求必须位于src下面,否则不能读取
代码实现
username=root password=1234
package com.itheima.sh.resourcebundle_02;import java.util.ResourceBundle;public class Test01 {public static void main(String[] args) {//1.获取ResourceBundle类的对象/*static ResourceBundle getBundle(String baseName) 根据指定的配置文件名获取ResourceBundle类的对象,不需要给后缀名举例:假设配置文件整体名字是:person.properties 这里只需给person 即可*/ResourceBundle bundle = ResourceBundle.getBundle("user");//2.String getString(String key) 根据key获取valueString username = bundle.getString("username");String password = bundle.getString("password");System.out.println(username+"--"+password);//root--1234} }
小结:
1.获取ResourceBundle类的对象
static ResourceBundle getBundle(String baseName) 根据指定的配置文件名获取ResourceBundle类的对象,不需要给后缀名举例:假设配置文件整体名字是:person.properties 这里只需给person 即可
2.String getString(String key) 根据key获取value
3.ResourceBundle只能操作src下面并且后缀名是.properties
4.如果配置文件中有中文(了解)
解决乱码:
3.缓冲流(掌握)
之前学习的基本流用来操作文件中的数据,但是效率有可能会低一些,为了提高读写效率,我们引入缓冲流.
缓冲流作用:就是为了提高读写效率。
名字:在之前学习的基本流的父类前面加Buffered
1.BufferedInputStream ----> 字节输入缓冲流
2.BufferedOutputStream ----> 字节输出缓冲流
3.BufferedReader ---->字符输入缓冲流
4.BufferedWriter ---->字符输出缓冲流
1.字节缓冲流
1.BufferedInputStream ----> 字节输入缓冲流 父类是:InputStream
BufferedInputStream(InputStream in) 参数in表示字节输入流,关联读取的文件 底层有数组
2.BufferedOutputStream ----> 字节输出缓冲流 父类是:OutputStream
BufferedOutputStream(OutputStream out) 参数out表示字节输出流,关联写的文件 底层有数组
代码演示:
需求:分别使用之前学习的基本流和现在的缓冲流复制文件,查看复制的时间
package com.itheima.sh.buffered_03;import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;/*需求:分别使用之前学习的基本流和现在的缓冲流复制文件,查看复制的时间*/
public class BufferedDemo01 {public static void main(String[] args) throws Exception{method_2();}//使用缓冲流复制private static void method_2() throws Exception{//1.创建字节输入流关联数据源文件D:\test\制服诱惑2.mp4FileInputStream fis = new FileInputStream("D:\\test\\制服诱惑2.mp4");//BufferedInputStream(InputStream in) 参数in表示字节输入流,关联读取的文件 底层有数组BufferedInputStream bis = new BufferedInputStream(fis);//2.创建字节输出流关联目的地文件F:\制服诱惑2.mp4FileOutputStream fos = new FileOutputStream("F:\\制服诱惑2.mp4");//BufferedOutputStream(OutputStream out) 参数out表示字节输出流,关联写的文件 底层有数组BufferedOutputStream bos = new BufferedOutputStream(fos);//3.定义字节数组byte[] buf = new byte[1024*8];//4.定义变量保存每次读取的字节个数int len;long start = System.currentTimeMillis();//5.使用循环读取数据while((len=bis.read(buf))!=-1){//6.使用字节输出流将内存中的数据写到目的地bos.write(buf,0,len);}long end = System.currentTimeMillis();System.out.println(end -start);//191ms//7.关闭资源 释放资源规律:从下往上释放bos.close();fos.close();bis.close();fis.close();}//使用之前学习的基本流复制文件//将D:\test\制服诱惑2.mp4复制到F:\制服诱惑2.mp4private static void method_1() throws Exception{//1.创建字节输入流关联数据源文件D:\test\制服诱惑2.mp4FileInputStream fis = new FileInputStream("D:\\test\\制服诱惑2.mp4");//2.创建字节输出流关联目的地文件F:\制服诱惑2.mp4FileOutputStream fos = new FileOutputStream("F:\\制服诱惑2.mp4");//3.定义字节数组byte[] buf = new byte[1024*8];//4.定义变量保存每次读取的字节个数int len;long start = System.currentTimeMillis();//5.使用循环读取数据while((len=fis.read(buf))!=-1){//6.使用字节输出流将内存中的数据写到目的地fos.write(buf,0,len);}long end = System.currentTimeMillis();System.out.println(end -start);//640ms//7.关闭资源fos.close();fis.close();}
}
小结:
字节缓冲流作用:提高读写效率的。
2.字符缓冲流
3.BufferedReader ---->字符输入缓冲流 ----父类Reader
构造方法:
BufferedReader(Reader in) 参数in表示关联的读取的文件路径
特有方法:
String readLine() 读取一个文本行放到返回值中,如果读取到文件末尾返回null
以前基本流模板:
char[] ch = new char[1024];
int len;
while((len=fr.read(ch))!=-1){......
}
高效流模板:
String line = null;//line保存每次读取一行数据
while((line=br.readLine())!=null){......
}
4.BufferedWriter ---->字符输出缓冲流------父类Writer
构造方法:
BufferedWriter(Writer out) 参数out表示关联的写的文件路径
特有方法:
void newLine() 写入一个行分隔符。
代码演示:
package com.itheima.sh.buffered_03;import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;/*字符缓冲流:1.BufferedReader ---->字符输入缓冲流 ----父类Reader构造方法:BufferedReader(Reader in) 参数in表示关联的读取的文件路径特有方法:String readLine() 读取一个文本行放到返回值中,如果读取到文件末尾返回null2.BufferedWriter ---->字符输出缓冲流------父类Writer构造方法:BufferedWriter(Writer out) 参数out表示关联的写的文件路径特有方法:void newLine() 写入一个行分隔符。*/
public class BufferedDemo02 {public static void main(String[] args) throws Exception{//需求:将D:\test\故事.txt复制到项目根目录//1.创建字符输入缓冲流对象关联数据源文件 D:\test\故事.txt//BufferedReader(Reader in) 参数in表示关联的读取的文件路径FileReader fr = new FileReader("D:\\test\\故事.txt");BufferedReader br = new BufferedReader(fr);//2.创建字符输出缓存流对象关联目的地文件根目录故事.txtFileWriter fw = new FileWriter("故事.txt");BufferedWriter bw = new BufferedWriter(fw);//3.读取数据String line = null;while((line=br.readLine())!=null){//4.写数据bw.write(line);//换行bw.newLine();//刷新bw.flush();}//5.释放资源bw.close();fw.close();br.close();fr.close();}
}
小结:
1.BufferedReader类提供了一次可以读取一行数据的特有方法:String readLine()读取文件末尾返回null
2.BufferedWriter类中提供了一个换行方法 void newLine()
3.字符缓冲流练习(课下必须完成)
package com.itheima.sh.buffered_03;import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.HashMap;/*需求:将123.txt中内容按顺序写到456.txt中分析:先读取一行数据:String line="3.侍中、侍郎郭攸之、费祎、董允等,此皆良实,志虑忠纯。。。"上述数据由三部分组成:1)序号 32)点 .3) 文字按照点进行切割 String[] split("切割符号")line.split(".") 这里参数的点表示任意字符 如果想表示真正的点 \\.String[] arr = line.split("\\.");数组中的数据:arr = {"3","侍中、侍郎郭攸之、费祎、董允等,此皆良实,志虑忠纯。。。"}将数组第一个数据序号变为整数---》3 Integer.parseInt("3") ---》 3将上述数组中的序号变为整数之后,作为Map集合的key存储 数组的第二个数据作为value存储到map集合HashMap<Integer,String> hm = new HashMap<Integer,String>();hm.put(Integer.parseInt("3"),"侍中、侍郎郭攸之、费祎、董允等,此皆良实,志虑忠纯。。。");遍历map集合根据序号取出value然后拼接,最后使用字符输出流写到目的地文件456.txt中步骤:1.创建Map集合对象2.创建字符输入缓冲流对象关联数据源文件123.txt3.创建字符输出缓冲流对象关联目的地文件456.txt4.使用字符输入缓冲流读取133.txt文件,每次读取异常数据存储到变量line中5.使用变量line调用切割方法line.split("\\."); 按照点进行切割6.取出数组的第一个数据变为整数存储到map集合键位置,第二个数据即文字存储到value位置7.遍历map集合取出key和value8.将key和value进行拼接并使用字符输出流写到目的地文件456.txt中9.关闭资源*/
public class Test01 {public static void main(String[] args) throws Exception {//1.创建Map集合对象HashMap<Integer, String> hm = new HashMap<Integer, String>();//2.创建字符输入缓冲流对象关联数据源文件123.txtBufferedReader br = new BufferedReader(new FileReader("123.txt"));//3.创建字符输出缓冲流对象关联目的地文件456.txtBufferedWriter bw = new BufferedWriter(new FileWriter("456.txt"));//4.使用字符输入缓冲流读取123.txt文件,每次读取异常数据存储到变量line中String line = null;while ((line = br.readLine()) != null) {// 5.使用变量line调用切割方法line.split("\\."); 按照点进行切割String[] arr = line.split("\\.");//6.取出数组的第一个数据变为整数存储到map集合键位置,第二个数据即文字存储到value位置//数组中的数据:arr = {"3","侍中、侍郎郭攸之、费祎、董允等,此皆良实,志虑忠纯。。。"}//将数组第一个数据即序号字符串3转换为整数
// int key = Integer.parseInt(arr[0]);hm.put(Integer.parseInt(arr[0]), arr[1]);}/*map的数据:3 侍中、侍郎郭攸之1 先帝创业未半而中道崩殂*///7.遍历map集合取出key和value/*for(int key=1;key<=hm.size();key++){//根据key获取valueString value = hm.get(key);// 8.将key和value进行拼接并使用字符输出流写到目的地文件456.txt中bw.write(key+"."+value);//换行bw.newLine();//刷新bw.flush();}*/for (int i = 1; i <= hm.size(); i++) {//i表示序号//将序号赋值给变量keyInteger key = i;//根据key获取valueString value = hm.get(key);// 8.将key和value进行拼接并使用字符输出流写到目的地文件456.txt中bw.write(key + "." + value);//换行bw.newLine();//刷新bw.flush();}//9.关闭资源bw.close();br.close();}
}
4.转换流(理解)
编码表
介绍
我们可以将编码表看作一个词典。
hello---->你好
编码表中:
字符(人类) 二进制(计算机)
A----------65------01000001
ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)支持英文字母 数字 符号。
在ASCII码表中一个字符占一个字节。
ISO-8859-1码表:支持欧洲 别名称为Latin1 拉丁文 内部有ASCII
在ISO-8859-1码表一个字符占一个字节
GBxxx字符集 :内部含有ASCII,针对汉字的码表
- GB2312 支持6000多汉字
- GBK :国标 支持几万
- GB18030:支持甲骨文。。。
在gbk码表中一个汉字占2个字节,英文字母 数字 特殊符号占一个字节
Unicode字符集:万国码表,支持所有国家的字符
- 主要包含:UTF-8 UTF-16 UTF-32
- 在UTF-8码表中:
- 英文字母 数字 特殊符号占1个字节
- 欧洲字符占2个字节
- 大部分汉字占3个字节
重点掌握的码表:
- ASCII 一个字符占一个字节。
- ISO-8859-1码表:在ISO-8859-1码表一个字符占一个字节
- GBK : 支持汉字 。在gbk码表中一个汉字占2个字节,英文字母 数字 特殊符号占一个字节
- UTF-8:英文字母 数字 特殊符号占1个字节 。大部分汉字占3个字节
编码、解码、乱码
编码:‘A’-----65----01000001 就是将我们看的懂的字符编码为我们看不懂的内容
解码:01000001 -----65 ---- ‘A’ 就是将我们看不懂的内容变为看的懂的字符
乱码:就是编码和解码使用的编码表不一致导致的
举例; 锁哥----按照GBK进行编码 锁:23736 哥 32622 解码:使用UTF-8 锁: 17262 哥 72626此时会产生乱码:Γゥ 解决乱码:按照之前的编码进行编码回去,然后在重新解码上述使用UTF-8乱码的,我们需要使用UTF-8编码回到之前状态在使用正确的码表GBK解码
编码引出的问题以及解决方案
package com.itheima.sh.charset_04;import java.io.FileInputStream;
import java.io.FileReader;
import java.io.InputStreamReader;/*需求:使用字符输入流读取E:\\1.txt文件中的数据,要求:1.txt使用GBK编码方式保存。我们将数据输出到控制台发现出现乱码:1.txt文件使用的编码表是GBK而我们使用字符输入流FileReader来读取文件,该流使用当前环境默认的编码表:UTF-8上述编码和解码使用编码表不一致了产生乱码。解决:不能使用FileReader类,因为该类不能随意指定编码表,只能是当前环境默认的编码表,我们可以使用其父类:InputStreamReader 属于字符输入转换流 父类-----Reader使用构造方法可以指定编码表:InputStreamReader(InputStream in, String charsetName)参数:in:关联要读取的文件的路径charsetName:指定的编码表*/
public class Demo01 {public static void main(String[] args) throws Exception{//1.创建字符输入流关联1.txt文件
// FileReader fr = new FileReader("E:\\1.txt");//创建字符输入流并指定编码表是GBKInputStreamReader fr = new InputStreamReader(new FileInputStream("E:\\1.txt"), "GBK");//2.读取数据char[] ch = new char[1024];int len;while((len=fr.read(ch))!=-1){//输出System.out.println(new String(ch,0,len));//你好}fr.close();}
}
小结:
1.FileReader表示字符输入流的基本流,但是只能是按照当前环境默认编码表
2.InputStreamReader作为FileReader的父类。表示字符输入转换流,可以指定任意的编码表。
3.InputStreamReader属于字符流,除了可以指定编码表,还可以将字节输入流转换为字符输入流
InputStreamReader fr = new InputStreamReader(new FileInputStream("E:\\1.txt"), "GBK");
OutputStreamWriter类
1.表示字符输出转换流。
2.该类的父类是Writer,属于字符流
3.该类可以指定编码表并且可以将字节输出流转换为字符输出流
OutputStreamWriter(OutputStream out, String charsetName) 参数:out:表示关联写数据的文件路径 属于字节输出流charsetName:指定编码表
OutputStreamWriter(OutputStream out) 创建使用默认字符编码的 OutputStreamWriter。
代码演示:
package com.itheima.sh.charset_04;import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.OutputStreamWriter;/*需求:使用字符输出转换流写数据,要求文件编码表使用的是GBK*/
public class Demo02 {public static void main(String[] args) throws Exception{//创建字符输出的基本流 FileWriter 使用当前环境默认的编码表即UTF-8
// FileWriter fw = new FileWriter("D:\\aaa\\5.txt");/*OutputStreamWriter(OutputStream out, String charsetName)参数:out:表示关联写数据的文件路径 属于字节输出流charsetName:指定编码表*/OutputStreamWriter fw = new OutputStreamWriter(new FileOutputStream("D:\\aaa\\6.txt"), "GBK");//写数据fw.write("黑马程序员");//刷新fw.flush();//释放资源fw.close();}
}
小结:
1.OutputStreamWriter表示字符输出转换流,父类是Writer
2.作用:
1)可以指定编码表
2)将字节输出流转换为字符输出流
OutputStreamWriter fw = new OutputStreamWriter(new FileOutputStream("D:\\aaa\\6.txt"), "GBK");
总结:
1.只要某个流的类末尾是Stream就属于字节流,否则就是字符流
2.末尾是Reader表示字符输入流 ; 末尾是Witer表示字符输出流
3.字符转换流:
转换流的练习(课下完成)
package com.itheima.sh.charset_04;import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;/*需求:把D:\\out.txt以UTF-8编码的文件转换为 以GBK编码的文件步骤:1.创建字符输入转换流对象,指定读取文件的编码表是UTF-82.创建字符输出转换流指定编码表是GBK将内存中的数据写到指定文件中3.使用输入流读取数据源文件D:\\out.txt4.使用字符输出转换流将数据写到目的地文件D:\\aaa\\7.txt5.关闭资源*/
public class Test01 {public static void main(String[] args) throws Exception{//1.创建字符输入转换流对象,指定读取文件的编码表是UTF-8InputStreamReader isr = new InputStreamReader(new FileInputStream("D:\\out.txt"), "UTF-8");//2.创建字符输出转换流指定编码表是GBK将内存中的数据写到指定文件中OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("D:\\aaa\\7.txt"), "GBK");//3.使用输入流读取数据源文件D:\\out.txtchar[] ch = new char[1024];int len;while((len=isr.read(ch))!=-1){//4.使用字符输出转换流将数据写到目的地文件D:\\aaa\\7.txtosw.write(ch,0,len);//刷新osw.flush();}//5.关闭资源osw.close();isr.close();}
}
5.序列化和反序列化流(掌握)
介绍
1.序列化流:可以将我们在程序中即内存中创建的对象长久保存到持久设备上。
Person p = new Person("锁哥",18);
2.反序列化流:就是将之前序列化到持久设备上的对象数据读取到内存中
使用
序列化流的类:ObjectOutputStream—父类 OutputStream
构造方法:
ObjectOutputStream(OutputStream out) 参数out表示字节输出流关联的写对象的文件的路径
写对象方法:序列化方法
void writeObject(Object obj) 将指定的对象写入 ObjectOutputStream。
反序列化流的类:ObjectInputStream — 父类 InputStream
构造方法
ObjectInputStream(InputStream in) 参数in表示字节输入流关联的读取对象所在的文件路径
读对象方法:反序列化方法
Object readObject() 从 ObjectInputStream 读取对象。 将读取的对象放到返回值中
上述两个流都是字节流
序列化和反序列使用注意:
- 被序列化或者反序列化的对象所属类必须实现序列化接口java.io.Serializable ,该接口表示序列化接口,没有任何成员,属于标记性接口。标记其实现类可以被序列化和反序列化。
代码实现:
package com.itheima.sh.object_stream_05;import java.io.Serializable;
import java.util.stream.Stream;
/*被序列化或者反序列化的对象所属类必须实现序列化接口java.io.Serializable ,该接口表示序列化接口,没有任何成员,属于标记性接口。标记其实现类可以被序列化和反序列化。*/
public class Person implements Serializable{//成员变量private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}public Person() {}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}
}package com.itheima.sh.object_stream_05;import java.io.FileOutputStream;
import java.io.ObjectOutputStream;/*序列化对象需求:将创建的自定义类Person的对象序列化到指定文件中*/
public class ObjectOutputStreamDemo01 {public static void main(String[] args) throws Exception{//1.创建Person对象Person p = new Person("锁哥", 19);//2.创建序列化流的对象//ObjectOutputStream(OutputStream out) 参数out表示字节输出流关联的写对象的文件的路径ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.txt"));//3.使用对象调用序列化方法序列化对象//void writeObject(Object obj) 将指定的对象写入 ObjectOutputStream。oos.writeObject(p);//4.关闭资源oos.close();}
}package com.itheima.sh.object_stream_05;import java.io.FileInputStream;
import java.io.ObjectInputStream;/*反序列化的*/
public class ObjectInputStreamDemo02 {public static void main(String[] args) throws Exception{//1.创建反序列流的对象//ObjectInputStream(InputStream in) 参数in表示字节输入流关联的读取对象所在的文件路径ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.txt"));//2.使用对象调用反序列化方法进行读取之前序列化到硬盘中的对象// Object readObject() 从 ObjectInputStream 读取对象。 将读取的对象放到返回值中Person p = (Person) ois.readObject();//3.获取姓名和年龄System.out.println(p.getName()+"----"+p.getAge());}
}
小结:
1.ObjectOutputStream表示序列化类,使用方法writeObject可以将任意对象写到持久设备上
2.ObjectInputStream表示反序列化类,使用方法readObject可以读取序列化的对象
3.被序列化或者反序列化的对象所属类必须实现序列化标记性接口java.io.Serializable
序列化和反序列化使用细节
1.被序列化或者反序列化的对象所属类必须实现序列化标记性接口java.io.Serializable
2.如果对象的某个成员变量的值不想被序列化到硬盘上,我们可以使用瞬态关键字transient修饰或者使用static修饰
//transient 表示瞬态 就是修饰的内容不会被序列化到硬盘上private transient String name;private static int age;
3.如果我们对于某个类的对象已经序列化了,然后我们又修改了该类的内容,然后不用直接序列化,而是反序列化就会出现异常:
java.io.InvalidClassException: com.itheima.sh.object_stream_05.Person;
local class incompatible:stream classdesc serialVersionUID = -2950267769722938759, local class serialVersionUID = -1806161995263188763说明:报上述无效的类异常原因:该类的序列版本号与从流中读取的类描述符的版本号不匹配 1.在java中如果一个类实现了序列化版本号Serializable,那么编译器就会根据该类的所有内容(类的成员变量 成员方法 修饰符等)在对应的.class文件中生成一个默认的版本号 serialVersionUID ,该版本号是一个long类型的,该版本号我们称为本地版本号:local class serialVersionUID 2.当我们使用序列化流将某个类的对象即Person对象序列化到文件中,同时也会将.class文件中的序列化版本号也写到指定文件中,那么此时该文件中也会有一个版本号,此版本号称为流中的版本号:stream classdesc serialVersionUID3.每次只要修改被序列化的类(Person),那么就会根据新的内容在本地重新生成一个新的本地版本号,如果我们不进行序列化,直接反序列化,由于生成的序列化文件中的流版本号还是之前的,那么就会导致本地新的版本号和流中反序列化的版本号不一致了,此时就会报异常4.每次在反序列化的时候都会拿本地版本号和流中版本号进行比对是否相等,如果不相等,则报异常InvalidClassException如果两个版本号相等:则可以正常反序列化5.为何要像上述这样做?为了安全6.这样做虽然安全了,但是对于程序员来说过于敏感。所以我们在实际开发中建议在需要被序列化的类中显示声明一个版本号,这样每次修改类就不会根据类的成员内容生成版本号了。public class Person implements Serializable{private static final long serialVersionUID = -8838871950488599879L;}
序列化集合
需求:我想序列化多个对象。
可以将多个对象存储到集合中,然后序列化集合即可。
package com.itheima.sh.object_stream_05;import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Collections;public class Test01 {public static void main(String[] args) throws Exception{//1.创建集合存储自定义Person类的对象ArrayList<Person> list = new ArrayList<>();//2.创建Person对象Person p1 = new Person("锁哥",18);Person p2 = new Person("岩岩",19);Person p3 = new Person("杨幂",20);Person p4 = new Person("冰冰",18);//3.添加数据Collections.addAll(list, p1, p2, p3, p4);//4.创建序列化对象ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("list.txt"));//5.调用方法进行序列化oos.writeObject(list);//6.创建反序列化类的对象ObjectInputStream ois = new ObjectInputStream(new FileInputStream("list.txt"));//7.反序列化集合ArrayList<Person> list2 = (ArrayList<Person>) ois.readObject();//8.遍历for (Person p : list2) {System.out.println(p.getName()+"----"+p.getAge());}}
}
day22【Properties、ResourceBundle工具类、缓冲流、转换流、序列化】课上相关推荐
- JavaSE(字符流、IO资源的处理、属性集、ResourceBundle工具类、缓冲流、转换流、序列化、打印流、装饰设计模式、commons-io工具包)
JavaSE 字符流 字符输入流[Reader] 字符输入流Reader类的概述 字符输入流Reader类的常用方法 FileReader类 FileReader类的概述 FileReader类的构造 ...
- 【26天高效学习Java编程】Day22:Java中的属性集-缓冲流-转换流-序列化流详解
本专栏将从基础开始,循序渐进,由浅入深讲解Java的基本使用,希望大家都能够从中有所收获,也请大家多多支持. 专栏地址:26天高效学习Java编程 相关软件地址:软件地址 所有代码地址:代码地址 如果 ...
- Properties 工具类 和 ResourceBundle 工具类
Properties 工具类 和 ResourceBundle 工具类(接上一篇JavaIO包) 2 Properties 工具类 2.1 Properties集合的基本使用 2.2 Properti ...
- 第十五章 IO流(转换流 字符流 字符缓冲流 打印流)
Java基础15 第十五章 IO流(转换流 字符流 字符缓冲流 打印流) 15.1 字符编码和字符集 15.1.1 字符编码 15.1.2 字符集 15.1.3 String类getBytes()方法 ...
- 解决修改properties 属性文件存在缓存问题,附带操作properties文件工具类
2019独角兽企业重金招聘Python工程师标准>>> 在做项目的时候有些数据不一定需要在数据库管理,例如数据库连接,定时任务等等的配置..有时候需要动态修改这些数据,但在修改完后, ...
- java 读取配置文件工具_java读取配置文件信息properties的工具类
java读取配置文件信息properties的工具类,介绍一个工具PropertyReader.java,读取项目配置文件信息 package mymail; import java.io.File; ...
- 工具类产品适合在微信公众号上运营吗?
1. 工具类产品适合在微信公众号上运营吗? 问题描述:如果工具类的产品,主要的核心服务功能搬到微信公众号上运营会有些什么优势和劣势,以及如何在公众号上实现流量变现? 答:微信公众号之前有三种分类:服务 ...
- java基础 io流 字节流 字符流 节点流 包装流 转换流 缓冲流 对象流 打印流 Properties类
目录 1.概念 2.常用的文件操作 2.1 创建文件 2.2 获取文件相关信息 2.3 目录的操作和文件删除 3. IO流原理及流的分类 3.1 流的分类 4.InputStream 字节输入流 4. ...
- io包下 文件类 字节流 字符流 缓冲流 转换流 序列化流 打印流
第一章 File类 1.1 概述 java.io.File 类是文件和目录路径名的抽象表示,主要用于文件和目录的创建.查找和删除等操作. 1.2 构造方法 public File(String pat ...
最新文章
- CentOS 7下源码编译安装新版本内核
- Python Module — WSME
- 项目开发管理工具---GitHub(一)
- 简易数字时钟软件详细制作过程
- (1)算法设计与分析_算法设计思路
- 计算机 金融工程 专业选择,金融工程专业对计算机编程能力是个什么要求呢
- 高等数学张宇18讲 第九讲 积分等式与积分不等式
- 您已购买此 App 内购买项目。此项目将免费恢复。This In-App purchase has already been bought.It will be restored for free.
- 程序员经常去的编程教学视频网站
- MathJax 支持的 Latex 符号总结(集合运算)
- 怎样能用计算机打出表白数字,数字表白大全 怎么用数字表白
- C++ 模板进阶(模板的特化)
- redmibook螃蟹网卡信号差问题
- 解决gradle下找不到符号错误
- 时间都去哪了。。。。
- 【Quectel移远展锐平台5G模组RX500U/RG200U使用指南(一)】
- NetBox在Win10下运行报错
- OS-Experiment for NUAA
- Echars学习笔记(后续接着更新和完善)
- 鸢尾花完整的python代码_鸢尾花BP算法实现 Python
热门文章
- Servlet生命周期总结
- 详细介绍 Node.js
- vue element ui 子组件向父组件传值
- VsCode安装和配置C++环境详细全流程
- ipguard外发文档的释放和释放到有什么区别
- 抢东西用的时间软件_紧急重要四象限软件用哪款?这款时间管理便签软件适合你...
- @touchmove.prevent 阻止苹果手机透过modal层触发底层滚动
- [RK3288]backlight pwm_bl控制双屏背光改写
- 统一了Excel和Python的神级编辑器GridStudio,安装起来确实不简单
- 深度学习进化编年大事记