IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Surpass Day25——Java IO流2 -> 正文阅读

[Java知识库]Surpass Day25——Java IO流2

目录

4.2 缓冲流专属

4.2.1 BufferedReader 读文件

4.2.2 InputStreamReader转换流

4.2.3 BufferedWriter读文件

4.3 数据流专属

4.3.1 DataOutputStream

4.3.2 DataInputStream 数据字节输入流

4.4 PrintStream标准输出流

4.5 File类

4.6 ObjectInputStream和ObjectOutputStream

4.7 IO+Properties的联合使用


*

4.2 缓冲流专属

4.2.1 BufferedReader 读文件

  • 带有缓冲区的字符输入流

  • 构造方法只能传入字符流

  • 使用这个流的时候不需要自定义char数组,或者说不需要自定义byte数组,自带缓冲

package com.java.javase.IO;
?
import java.io.BufferedReader;
import java.io.FileReader;
?
public class BufferedReaderTest01 {
 ? ?public static void main(String[] args) throws Exception{
 ? ? ? ?// 创建一个使用默认大小输入缓冲区的缓冲字符输入流
 ? ? ? ?FileReader reader=new FileReader("E:\\01javaSE\\test\\test.txt");
 ? ? ? ?// 当一个流的构造方法中需要一个流的时候,这个被传入的流叫做: 节点流
 ? ? ? ?// 外部负责包装的流叫做包装流,也称做处理流
 ? ? ? ?// 就当前这个程序来说,FileReader就是一个节点流,BufferedReader就是包装流/处理流
 ? ? ? ?BufferedReader br=new BufferedReader(reader);
?
 ? ? ? ?// 读取一个文本行(不带有换行符),返回值是一个字符串,当读取到文件末尾没有数据可以读取时,返回值为null
 ? ? ? ?String s=null;
 ? ? ? ?while ((s=br.readLine())!=null){
 ? ? ? ? ? ?System.out.println(s);
 ? ? ?  }
 ? ? 
 ? ? ? ?// 对于包装流来说,只需要关闭最外层的流就行,里面的节点流会自动关闭
 ? ? ? ?br.close();
 ?  }
}

在上面使用构造方法创建BufferedReader对象的时候,构造方法中只能传入字符流,那如果我要传入的是FileInputStream文件字节输入流呢?答案肯定是不行的,肯定会报错!怎么解决呢?可以通过转换流转换

4.2.2 InputStreamReader转换流

package com.java.javase.IO;
?
import java.io.*;
?
public class BufferedReaderTest01 {
 ? ?public static void main(String[] args) throws Exception{
 ? ? ? ?// BufferedReader的构造方法中只能传入字符流,但是这里我想要传入一个字节流
 ? ? ? ?FileInputStream in=new FileInputStream("E:\\01javaSE\\test\\test.txt");
?
 ? ? ? ?// 通过转换流转换,将字节流转换为字符流
 ? ? ? ?// in在这里是一个节点流,reader是包装流
 ? ? ? ?InputStreamReader reader=new InputStreamReader(in);
 ? ? 
 ? ? ? ?// 这个构造方法只能传一个字符流,不能传字节流,但是上面我们已经通过转换流转换了
 ? ? ? ?// reader在这里是一个节点流,br是包装流
 ? ? ? ?BufferedReader br=new BufferedReader(reader);
 ? ? 
 ? ? ? ?String line=null;
 ? ? ? ?while ((line=br.readLine())!=null){
 ? ? ? ? ? ?System.out.println(line);
 ? ? ?  }
 ? ? 
 ? ? ? ?// 关闭最外层
 ? ? ? ?br.close();
 ?  }
}

将代码合并的写法

package com.java.javase.IO;
?
import java.io.*;
?
public class BufferedReaderTest01 {
 ? ?public static void main(String[] args) throws Exception{
 ? ? ? ?BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream("E:\\01javaSE\\test\\test.txt")));
?
 ? ? ? ?String line=null;
 ? ? ? ?while ((line=br.readLine())!=null){
 ? ? ? ? ? ?System.out.println(line);
 ? ? ?  }
 ? ? 
 ? ? ? ?// 关闭最外层
 ? ? ? ?br.close();
 ?  }
}

4.2.3 BufferedWriter读文件

  • 带有缓冲区的字符输出流

  • 用法与BufferedReader相似

package com.java.javase.IO;
?
import java.io.*;
?
public class BufferedWriterTest {
 ? ?public static void main(String[] args) throws Exception{
 ? ? ? ?// 以追加的方式写入
 ? ? ? ?BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("E:\\01javaSE\\test\\test.txt",true)));
?
 ? ? ? ?bw.write("today is Monday!");
 ? ? 
 ? ? ? ?// 刷新
 ? ? ? ?bw.flush();
 ? ? ? ?// 关闭最外层
 ? ? ? ?bw.close();
 ?  }
}

4.3 数据流专属

4.3.1 DataOutputStream

这个流可以将数据连同数据的类型一并写入文件(该文件不是普通的文本文档)

package com.java.javase.IO;
?
import java.io.DataOutputStream;
import java.io.FileOutputStream;
// DataOutputStream写的文件,只能使用DataOutputStream去读,并且读的时候需要提前知道写入的顺序
// 读的顺序需要和写的顺序一致,才可以正常取出数据
?
public class DataOutputStreamTest01 {
 ? ?public static void main(String[] args)throws Exception {
 ? ? ? ?DataOutputStream dos=new DataOutputStream(new FileOutputStream("E:\\01javaSE\\test\\test1.txt"));
 ? ? ? ?byte b=100;
 ? ? ? ?short s=200;
 ? ? ? ?int i=10;
 ? ? ? ?long f=44L;
 ? ? ? ?float g=3.0F;
 ? ? ? ?double d=3.14;
 ? ? ? ?boolean sex=false;
 ? ? ? ?char c='a';
 ? ? ? ?
?
 ? ? ? ?// 将数据以及数据的类型一并写入文件当中
 ? ? ? ?dos.writeByte(b);
 ? ? ? ?dos.writeShort(s);
 ? ? ? ?dos.writeInt(i);
 ? ? ? ?dos.writeLong(f);
 ? ? ? ?dos.writeFloat(g);
 ? ? ? ?dos.writeDouble(d);
 ? ? ? ?dos.writeBoolean(sex);
 ? ? ? ?dos.writeChar(c);
 ? ? 
 ? ? ? ?dos.flush();
 ? ? ? ?dos.close();
 ?  }
?
}

当我们使用记事本打开写入数据的文件时,会出现乱码,无法正常显示文件(如下图),如果要正常读取我们用DataOutputStream写入的数据,就要用到下面要讲的DataInputStream

4.3.2 DataInputStream 数据字节输入流

  • DataOutputStream写的文件,只能使用DataInputStream去读,并且读的时候你需要提前知道写入的顺序

  • 读的顺序需要和写的顺序一致,才可以正常取出数据

package com.java.javase.IO;
?
import java.io.DataInputStream;
import java.io.FileInputStream;
// DataInputStream ————数据字节输入流
?
public class DataInputStreamTest01 {
 ? ?public static void main(String[] args)throws Exception {
 ? ? ? ?DataInputStream dis =new DataInputStream(new FileInputStream("E:\\01javaSE\\test\\test1.txt"));
 ? ? ? ?byte a=dis.readByte();
 ? ? ? ?short b=dis.readShort();
 ? ? ? ?int c=dis.readInt();
 ? ? ? ?long d=dis.readLong();
 ? ? ? ?float e=dis.readFloat();
 ? ? ? ?double f=dis.readDouble();
 ? ? ? ?boolean g=dis.readBoolean();
 ? ? ? ?char h=dis.readChar();
?
 ? ? ? ?System.out.println(a);
 ? ? ? ?System.out.println(b);
 ? ? ? ?System.out.println(c);
 ? ? ? ?System.out.println(d);
 ? ? ? ?System.out.println(e);
 ? ? ? ?System.out.println(f);
 ? ? ? ?System.out.println(g);
 ? ? ? ?System.out.println(h);
 ?  }
}

输出结果

100
200
10
44
3.0
3.14
false
a

4.4 PrintStream标准输出流

标准的字节输出流 默认输出到控制台

package com.java.javase.IO;
?
import java.io.PrintStream;
?
public class PrintStreamTest01 {
 ? ?public static void main(String[] args) {
 ? ? ? ?// 联合起来写
 ? ? ? ?System.out.println("hello world!");
?
 ? ? ? ?// 分开写
 ? ? ? ?PrintStream ps=System.out;
 ? ? ? ?ps.println("helo zhangsan");
 ? ? ? ?ps.println(100);
 ? ? 
 ? ? ? ?// 标准输出流不需要手动关闭
 ?  }
?
}

System这个类中有这样一个属性

因此System.out实际上代表一个PrintStream对象

改变标准输出流的方向

package com.java.javase.IO;
?
?
import java.io.FileOutputStream;
import java.io.PrintStream;
?
public class PrintStreamTest01 {
 ? ?public static void main(String[] args) throws Exception{
 ? ? ? ?// 改变标准输出流的方向,使其输出不再指向控制台,而指向我们指定的文件,需要用到System类的setOut()方法
 ? ? ? ?PrintStream printStream=new PrintStream(new FileOutputStream("E:\\01javaSE\\test\\test1.txt"));
 ? ? ? ?System.setOut(printStream);
 ? ? ? ?System.out.println("hello world");
 ? ? ? ?System.out.println(999999999);
 ?  }
}
一个好用的日志工具的编写

package com.java.javase.IO;
?
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.Date;
?
/**
 ? ?日志工具
 */
public class LogUtil {
 ? ?public static void log(String msg) throws Exception {
 ? ? ? ?try{
 ? ? ? ? ? ?// 指向一个日志文件
 ? ? ? ? ? ?PrintStream out=new PrintStream(new FileOutputStream("E:\\01javaSE\\test\\log.txt",true));
 ? ? ? ? ? ?// 改变输出方向
 ? ? ? ? ? ?System.setOut(out);
 ? ? ? ? ? ?// 当前时间格式化
 ? ? ? ? ? ?Date nowTime=new Date();
 ? ? ? ? ? ?SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
 ? ? ? ? ? ?String strTime=sdf.format(nowTime);
 ? ? ? ? ? ?// 输出到日志文件
 ? ? ? ? ? ?System.out.println(strTime+" : "+msg);
 ? ? ?  }catch (FileNotFoundException e){
 ? ? ? ? ? ?e.printStackTrace();
 ? ? ?  }
 ?  }
}

测试类

package com.java.javase.IO;
?
public class Test {
 ? ?public static void main(String[] args) throws Exception{
 ? ? ? ?LogUtil.log("用户开始登录!");
 ? ? ? ?LogUtil.log("用户登陆中!");
 ? ? ? ?LogUtil.log("用户退出登录!");
 ?  }
}

4.5 File类

  • File类和四大家族没有关系,所以File类不能完成文件的读和写

  • File对象表示文件和目录路径名的抽象表示形式

  • E:\01javaSE\test 是一个File对象

  • E:\01javaSE\test\log.txt 也是一个File对象

  • 一个File对象有可能对应的是目录,也可能是文件

我们需要掌握File类中常用的方法

package com.java.javase.IO;
?
import java.io.File;
?
public class FileTest01 {
 ? ?public static void main(String[] args) throws Exception{
 ? ? ? ?// 创建一个File对象
 ? ? ? ?File f1=new File("E:\\01javaSE\\test\\log1.txt");
?
 ? ? ? ?// 判断是否存在
 ? ? ? ?System.out.println(f1.exists());
 ? ? 
 ? ? ? ?// 如果E:\01javaSE\test不存在,则以文件的形式创建出来
 ? ? ? ?if(!f1.exists()){
 ? ? ? ? ? ?// 以文件形式新建
 ? ? ? ? ? ?f1.createNewFile();
 ? ? ?  }
 ?  }
?
}

创建多重目录

package com.java.javase.IO;
?
import java.io.File;
?
public class FileTest01 {
 ? ?public static void main(String[] args) throws Exception{
 ? ? ? ?// 创建一个File对象
 ? ? ? ?File f1=new File("E:/01javaSE/test/a/b/c/d");
 ? ? ? ?if (!f1.exists()){
 ? ? ? ? ? ?// 以多重目录的形式创建
 ? ? ? ? ? ?f1.mkdirs();
 ? ? ?  }
 ?  }
}

获取文件的父路径

package com.java.javase.IO;
?
import java.io.File;
?
public class FileTest01 {
 ? ?public static void main(String[] args) throws Exception {
 ? ? ? ?// 创建一个File对象
 ? ? ? ?File f1 = new File("E:\\01javaSE\\test\\log.txt");
 ? ? ? ?// 获取文件的父路径
 ? ? ? ?String parentPath = f1.getParent();
 ? ? ? ?System.out.println(parentPath);
 ?  }
}

获取当前目录下的所有子文件

package com.java.javase.IO;
import java.io.File;
?
/**
?
 * File中的listFiles方法
 ? */
public class FileTest02 {
    public static void main(String[] args) {
 ? ? ?  File f1=new File("E:\\01javaSE\\test");
 ? ? ?      // 获取当前目录下所有的子文件
 ? ? ?      File[] files=f1.listFiles();
 ? ? ?      for(File file:files){
 ? ? ? ? ?      System.out.println(file.getAbsolutePath());
 ? ? ?      }
 ?  }
}

其它常用方法

package com.java.javase.IO;
?
?
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
?
public class FileTest02 {
 ? ?public static void main(String[] args) {
 ? ? ? ?File f1=new File("E:\\01javaSE\\test\\log.txt");
 ? ? ? ?// 获取文件名
 ? ? ? ?System.out.println("文件名:"+f1.getName());
?
 ? ? ? ?// 判断是否是一个目录
 ? ? ? ?System.out.println(f1.isDirectory());
 ? ? 
 ? ? ? ?// 判断是否是一个文件
 ? ? ? ?System.out.println(f1.isFile());
 ? ? 
 ? ? ? ?// 获取文件最后一次修改时间
 ? ? ? ?// 这个毫秒数是从1970年到当前时间的总毫秒数
 ? ? ? ?long haoMiao=f1.lastModified();
 ? ? 
 ? ? ? ?// 将总毫秒数转换成日期
 ? ? ? ?Date time=new Date(haoMiao);
 ? ? ? ?SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
 ? ? ? ?String strTime=sdf.format(time);
 ? ? ? ?System.out.println(strTime);
 ? ? 
 ? ? ? ?// 获取文件大小(多少字节)
 ? ? ? ?System.out.println(f1.length());
 ?  }
?
}

练习:拷贝目录

package com.java.javase.IO;
?
import java.io.*;
?
public class Copy {
 ? ?public static void main(String[] args) {
 ? ? ? ?// 拷贝源
 ? ? ? ?String pathName1="E:\\01javaSE\\02-JavaSE进阶版";
 ? ? ? ?File srcFile=new File(pathName1);
?
 ? ? ? ?// 拷贝目标
 ? ? ? ?String pathName2="E:\\01javaSE\\dest";
 ? ? ? ?File destFile=new File(pathName2);
 ? ? 
 ? ? ? ?// 调用方法拷贝
 ? ? ? ?copyDir(pathName1,pathName2,srcFile);
 ?  }
 ? ? 
 ? ?/**
 ? ? * 拷贝目录
 ? ? * @param srcFile 拷贝源
 ? ? */
 ? ?private static void copyDir(String pathName1,String pathName2,File srcFile) {
 ? ? ? ?// 获取拷贝源下面的所有File对象(可能是文件也可能是目录)
 ? ? ? ?File[] files=srcFile.listFiles();
 ? ? ? ?if (files==null){
 ? ? ? ? ? ?return;
 ? ? ?  }
 ? ? ? ?for(File file:files){
 ? ? ? ? ? ?// 第一种情况:如果遇到的是一个文件则拷贝
 ? ? ? ? ? ?if(file.isFile()){
 ? ? ? ? ? ? ? ?FileInputStream fis=null;
 ? ? ? ? ? ? ? ?FileOutputStream fos=null;
 ? ? ? ? ? ? ? ?try {
 ? ? ? ? ? ? ? ? ? ?int n=pathName1.length();
 ? ? ? ? ? ? ? ? ? ?String resultPath=pathName2+file.getAbsolutePath().substring(n);
 ? ? ? ? ? ? ? ? ? ?System.out.println(resultPath);
 ? ? ? ? ? ? ? ? ? ?File f1=new File(resultPath);
 ? ? ? ? ? ? ? ? ? ?if (!f1.exists()){
 ? ? ? ? ? ? ? ? ? ? ? ?f1.createNewFile();
 ? ? ? ? ? ? ? ? ?  }
 ? ? ? ? ? ? ? ? ? ?fis=new FileInputStream(file.getAbsolutePath());
 ? ? ? ? ? ? ? ? ? ?fos=new FileOutputStream(resultPath,true);
 ? ? ? ? ? ? ? ? ? ?// 一次拷贝1MB
 ? ? ? ? ? ? ? ? ? ?byte[]bytes=new byte[1024*1024];
 ? ? ? ? ? ? ? ? ? ?int readCount=0;
 ? ? ? ? ? ? ? ? ? ?while((readCount=fis.read(bytes))!=-1){
 ? ? ? ? ? ? ? ? ? ? ? ?fos.write(bytes,0,readCount);
 ? ? ? ? ? ? ? ? ?  }
 ? ? ? ? ? ? ? ? ? ?fos.flush();
 ? ? 
 ? ? ? ? ? ? ?  } catch (FileNotFoundException e) {
 ? ? ? ? ? ? ? ? ? ?e.printStackTrace();
 ? ? ? ? ? ? ?  }catch (IOException e){
 ? ? ? ? ? ? ? ? ? ?e.printStackTrace();
 ? ? ? ? ? ? ?  }finally {
 ? ? ? ? ? ? ? ? ? ?if(fis!=null){
 ? ? ? ? ? ? ? ? ? ? ? ?try {
 ? ? ? ? ? ? ? ? ? ? ? ? ? ?fis.close();
 ? ? ? ? ? ? ? ? ? ? ?  } catch (IOException e) {
 ? ? ? ? ? ? ? ? ? ? ? ? ? ?e.printStackTrace();
 ? ? ? ? ? ? ? ? ? ? ?  }
 ? ? ? ? ? ? ? ? ?  }
 ? ? ? ? ? ? ? ? ? ?if(fos!=null){
 ? ? ? ? ? ? ? ? ? ? ? ?try {
 ? ? ? ? ? ? ? ? ? ? ? ? ? ?fos.close();
 ? ? ? ? ? ? ? ? ? ? ?  } catch (IOException e) {
 ? ? ? ? ? ? ? ? ? ? ? ? ? ?e.printStackTrace();
 ? ? ? ? ? ? ? ? ? ? ?  }
 ? ? ? ? ? ? ? ? ?  }
 ? ? ? ? ? ? ?  }
 ? ? ? ? ?  }
 ? ? 
 ? ? ? ? ? ?// 第二种情况:如果遇到的是一个文件夹则递归遍历,并且要创建相应的文件夹
 ? ? ? ? ? ?// 创建文件夹目录
 ? ? ? ? ? ?if(file.isDirectory()){
 ? ? ? ? ? ? ? ?int n=pathName1.length();
 ? ? ? ? ? ? ? ?// 拿到目标目录
 ? ? ? ? ? ? ? ?/**
 ? ? ? ? ? ? ? ? * E:\01javaSE\dest\a
 ? ? ? ? ? ? ? ? * E:\01javaSE\dest\a\b
 ? ? ? ? ? ? ? ? * E:\01javaSE\dest\a\b\c
 ? ? ? ? ? ? ? ? * E:\01javaSE\dest\a\b\c\d
 ? ? ? ? ? ? ? ? */
 ? ? ? ? ? ? ? ?String resultPath=pathName2+file.getAbsolutePath().substring(n);
 ? ? ? ? ? ? ? ?File f1=new File(resultPath);
 ? ? ? ? ? ? ? ?if (!f1.exists()){
 ? ? ? ? ? ? ? ? ? ?f1.mkdirs();
 ? ? ? ? ? ? ?  }
 ? ? ? ? ? ? ? ?// 递归调用
 ? ? ? ? ? ? ? ?copyDir(pathName1,pathName2,file);
 ? ? ? ? ?  }
 ? ? 
 ? ? ?  }
 ?  }
}

4.6 ObjectInputStream和ObjectOutputStream

在介绍ObjectInputStream和ObjectOutputStream之前,我们先来看一下什么是序列化和反序列化

ObjectOutputStream是负责序列化的,ObjectInputStream是负责反序列化的

首先准备一个学生类

package com.java.javase.xuLieHua;
?
import java.io.Serializable;
?
public class Student implements Serializable {
 ? ?private ?int no;
 ? ?private String name;
?
 ? ?public Student() {
 ?  }
 ? ? 
 ? ?public Student(int no, String name) {
 ? ? ? ?this.no = no;
 ? ? ? ?this.name = name;
 ?  }
 ? ? 
 ? ?public int getNo() {
 ? ? ? ?return no;
 ?  }
 ? ? 
 ? ?public void setNo(int no) {
 ? ? ? ?this.no = no;
 ?  }
 ? ? 
 ? ?public String getName() {
 ? ? ? ?return name;
 ?  }
 ? ? 
 ? ?public void setName(String name) {
 ? ? ? ?this.name = name;
 ?  }
 ? ? 
 ? ?@Override
 ? ?public String toString() {
 ? ? ? ?return "Student{" +
 ? ? ? ? ? ? ? ?"no=" + no +
 ? ? ? ? ? ? ? ?", name='" + name + '\'' +
 ? ? ? ? ? ? ? ?'}';
 ?  }
?
}

如果你希望某一个属性不参与序列化,可以在该属性前加关键字 transient (表示游离的,不参与序列化)

private ?int no;
private transient String name;
序列化

package com.java.javase.xuLieHua;
?
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
// java.io.NotSerializableException: Student对象不支持序列化!
// 参与序列化和反序列化的对象必须实现Serializable接口————只是一个标志接口,起到标识的作用
// Serializable这个标志接口是给java虚拟机参考的,java虚拟机看到这个接口之后,会为该类自动生成一个序列化版本号
public class ObjectOutputStreamTest01 {
 ? ?public static void main(String[] args) throws Exception{
 ? ? ? ?Student s=new Student(110,"张三");
?
 ? ? ? ?ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("E:\\01javaSE\\test\\xuliehua.txt"));
 ? ? ? ?oos.writeObject(s);
 ? ? 
 ? ? ? ?oos.flush();
 ? ? ? ?oos.close();
 ?  }
?
}

反序列化

package com.java.javase.xuLieHua;
?
import java.io.FileInputStream;
import java.io.ObjectInputStream;
// 反序列化
?
public class ObjectInputStreamTest01 {
 ? ?public static void main(String[] args)throws Exception {
 ? ? ? ?ObjectInputStream ois=new ObjectInputStream(new FileInputStream("E:\\01javaSE\\test\\xuliehua.txt"));
 ? ? ? ?Object obj=ois.readObject();
 ? ? ? ?System.out.println(obj.toString());
 ? ? ? ?ois.close();
 ?  }
}

一次性序列化多个对象

package com.java.javase.xuLieHua;
?
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
// 一次性序列化多个对象
// 可以将对象放到集合当中,序列化集合
// 参与序列化的集合以及集合中的元素都需要实现java.io.Serializable接口
?
public class ObjectOutputStreamTest02 {
 ? ?public static void main(String[] args) throws Exception{
 ? ? ? ?List<Student> studentList=new ArrayList<>();
 ? ? ? ?studentList.add(new Student(110,"lisi"));
 ? ? ? ?studentList.add(new Student(111,"zhangsan"));
 ? ? ? ?studentList.add(new Student(112,"wangwu"));
 ? ? ? ?ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("E:\\01javaSE\\test\\xuliehua.txt"));
 ? ? ? ?oos.writeObject(studentList);
?
 ? ? ? ?oos.flush();
 ? ? ? ?oos.close();
 ?  }
?
}

与之对应的,一次性反序列化多个对象

package com.java.javase.xuLieHua;
?
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.util.List;
?
public class ObjectInputStreamTest02 {
 ? ?public static void main(String[] args)throws Exception {
 ? ? ? ?ObjectInputStream ois=new ObjectInputStream(new FileInputStream("E:\\01javaSE\\test\\xuliehua.txt"));
 ? ? ? ?List<Student> studentList=(List<Student>)ois.readObject();
 ? ? ? ?for(Student student:studentList){
 ? ? ? ? ? ?System.out.println(student);
 ? ? ?  }
?
 ? ? ? ?ois.close();
 ?  }
?
}

关于序列化版本号的理解

  • 当我们首次编写好一个学生类,使用序列化手段将对象存储到硬盘中,在该过程中,Java虚拟机看到Serializable接口之后,会自动帮我们生成一个序列化版本号

  • 过了很多很多年,Student这个类的源码改动了(比如增加了某个属性),源代码改动之后,需要重新编译,编译之后生成了全新的字节码文件

  • class文件再次运行的时候,java虚拟机生成的序列化版本号也会发生相应的改变

  • 这时再次运行反序列化操作的时候就会报出错误

因此序列化版本号有什么作用呢?可以用来区分类

Java语言中区分类的机制:

1、首先通过类名进行对比,如果类名不一样,则肯定不是同一个类 ? 2、如果类名一样,再根据序列化版本号进行区分

自动生成序列化版本号的缺点:

一旦代码确定之后,不能进行后续的修改,因为只要修改,必然会重新编译,此时会生成全新的序列化版本号,这个时候java虚拟机会认为这是一个全新的类

结论:

凡是一个类实现了Serializable接口,建议给该类提供一个固定不变的序列化版本号,这样,以后即使这个类改变了,但是版本号不变,java虚拟机会认为是同一个类

private static final long serialVersionUID=1L;

4.7 IO+Properties的联合使用

IO流:文件的读和写

Properties:是一个集合,key和value都是String类型

新建一个classinfo.properties配置文件

name=lisi
password=123456

编写读取代码

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-02-07 13:35:18  更:2022-02-07 13:35:49 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 11:51:10-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码