对象流

java.io.ObjectOutputStream和ObjectInputSteam

对象流是一对高级流,在流连接中的作用是进行对象的序列化与反序列化。

对象序列化:将一个java对象按照其结构转换为一组字节的过程

对象反序列化:将一组字节还原为java对象(前提是这组字节是一个对象序列化得到的字节)

对象序列化的流连接操作原理图:

package io;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream; /**
* 对象流
* java.io.ObjectOutputStream和ObjectInputSteam
* 对象流是一对高级流,在流连接中的作用是进行对象的序列化与反序列化
*
* 对象序列化:将一个java对象按照其结构转换为一组字节的过程
* 对象反序列化:将一组字节还原为java对象(前提是这组字节是一个对象序列化得到的字节)
*/
public class OOSDemo {
public static void main(String[] args) throws IOException {
//将一个Person对象写入文件person.obj
String name = "苍老师";
int age = 18;
String gender = "女";
String[] otherInfo = {"是一名台词不多的演员","来自岛国","爱好写大字","广大男性同胞的启蒙老师"};
Person p = new Person(name,age,gender,otherInfo);
System.out.println(p); FileOutputStream fos = new FileOutputStream("person.obj");
ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(p);
System.out.println("写出完毕!"); oos.close(); }
}

对象反序列化


package io; import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream; /**
* 使用对象输入流完成对象的反序列化
*/
public class OISDemo {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//从person.obj文件中将对象反序列化回来
FileInputStream fis = new FileInputStream("person.obj");
ObjectInputStream ois = new ObjectInputStream(fis);
/*
Object readObject()
该方法会进行对象的反序列化,如果对象流通过其连接的流读取的字节分析并非
是一个java对象时,会抛出异常:ClassNotFoundException
*/
Person p = (Person)ois.readObject();
System.out.println(p);
}
}

需要进行序列化的类必须实现接口:java.io.Serializable

实现序列化接口后最好主动定义序列化版本号这个常量。

这样一来对象序列化时就不会根据类的结构生成一个版本号,而是使用该固定值。

那么反序列化时,只要还原的对象和当前类的版本号一致就可以进行还原。

transient关键字可以修饰属性,用于在进行对象序列化时忽略不必要的属性,达到对象瘦身的目的

package io;

import java.io.Serializable;
import java.util.Arrays; /**
* 使用当前类实例测试对象流的读写操作
*/
public class Person implements Serializable {
public static final long serialVersionUID = 1L;
private String name;//姓名
private int age;//年龄
private String gender;//性别
private String[] otherInfo;//其他信息 public Person(String name, int age, String gender, String[] otherInfo) {
this.name = name;
this.age = age;
this.gender = gender;
this.otherInfo = otherInfo;
} 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;
} public String getGender() {
return gender;
} public void setGender(String gender) {
this.gender = gender;
} public String[] getOtherInfo() {
return otherInfo;
} public void setOtherInfo(String[] otherInfo) {
this.otherInfo = otherInfo;
} @Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
", otherInfo=" + Arrays.toString(otherInfo) +
'}';
}
}

字符流

  • java将流按照读写单位划分为字节流与字符流.
  • java.io.InputStream和OutputStream是所有字节流的超类
  • 而java.io.Reader和Writer则是所有字符流的超类,它们和字节流的超类是平级关系.
  • Reader和Writer是两个抽象类,里面规定了所有字符流都必须具备的读写字符的相关方法.
  • 字符流最小读写单位为字符(char),但是底层实际还是读写字节,只是字符与字节的转换工作由字符流完成.

转换流

java.io.InputStreamReader和OutputStreamWriter

它们是字符流非常常用的一对实现类同时也是一对高级流,实际开发中我们不直接操作它们,但是它们在流连接中是非常重要的一环.

使用转换输出流向文件中写入文本数据

package io;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter; /**
* 字符流
* java将流按照读写单位划分为字节流与字符流.
* java.io.InputStream和OutputStream是所有字节流的超类
* 而java.io.Reader和Writer则是所有字符流的超类,它们是平级关系.
*
* Reader和Writer是两个抽象类,里面规定了所有字符流都必须具备的读写字符的相关方法.
* 字符流最小读写单位为字符(char),但是底层实际还是读写字节,只是字符与字节的转换工作由
* 字符流完成.
*
* 转换流
* java.io.InputStreamReader和OutputStreamWriter
* 它们是字符流非常常用的一对实现类同时也是一对高级流,实际开发中我们不直接操作它们,但是
* 它们在流连接中是非常重要的一环.
*/
public class OSWDemo {
public static void main(String[] args) throws IOException {
//向文件osw.txt中写入文字
FileOutputStream fos = new FileOutputStream("osw.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos,"UTF-8");
osw.write("我可以接受你的所有,所有小脾气.");
osw.write("我可以带你去吃很多,很多好东西.");
System.out.println("写出完毕!");
osw.close();
}
}

使用转换输入流读取文本文件

package io;

import java.io.*;

/**
* 转换字符输入流
* 可以将读取的字节按照指定的字符集转换为字符
*/
public class ISRDemo {
public static void main(String[] args) throws IOException {
//将osw.txt文件中的所有文字读取回来.
FileInputStream fis = new FileInputStream("osw.txt");
InputStreamReader isr = new InputStreamReader(fis,"UTF-8");
/*
字符流读一个字符的read方法定义:
int read()
读取一个字符,返回的int值实际上表示的是一个char(低16位有效).如果返回的
int值表示的是-1则说明EOF
*/
//测试读取文件中第一个字
// int d = isr.read();
// char c = (char)d;
// System.out.println(c); //循环将文件所有字符读取回来
int d;
while((d = isr.read()) != -1){
System.out.print((char)d);
} isr.close();
}
}

转换流的意义:

实际开发中我们还有功能更好用的字符高级流.但是其他的字符高级流都有一个共通点:不能直接连接在字节流上.而实际操作设备的流都是低级流同时也都是字节流.因此不能直接在流连接中串联起来.转换流是一对可以连接在字节流上的字符流,其他的高级字符流可以连接在转换流上.在流连接中起到"转换器"的作用(负责字符与字节的实际转换)

缓冲字符流

缓冲字符输出流:java.io.PrintWriter

java.io.BufferedWriter和BufferedReader

缓冲字符流内部也有一个缓冲区,读写文本数据以块读写形式加快效率.并且缓冲流有一个特别的功能:可以按行读写文本数据.

java.io.PrintWriter具有自动行刷新的缓冲字符输出流,实际开发中更常用.它内部总是会自动连接BufferedWriter作为块写加速使用.

package io;

import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException; /**
* 缓冲字符流
* 缓冲字符流是一对高级流,在流连接中的作用是提高读写文本数据的效率,并且
* 可以安行读写字符串.
* java.io.BufferedReader和BufferedWriter
*
* 实际开发中缓冲字符输出流我们更常用的是PrintWriter,具有自动行刷新功能
* 的缓冲字符输出流,其内部总是连接BufferedWriter作为缓冲加速使用.
*/
public class PWDemo1 {
public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
/*
PrintWriter提供了对文件操作的构造方法:
PrintWriter(String path)
PrintWriter(File file)
*/
//向文件中写入字符串
PrintWriter pw = new PrintWriter("pw.txt","UTF-8");
pw.println("我看过沙漠下暴雨");
pw.println("看过大海亲吻鲨鱼");
pw.println("看过黄昏追逐黎明");
pw.println("没看过你");
System.out.println("写出完毕!");
pw.close(); }
}

在流链接中使用PW

package io;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Scanner; /**
* 在流连接中使用PW
*/
public class PWDemo2 {
public static void main(String[] args) throws FileNotFoundException {
//文件字节输出流(是一个低级流),向文件中写入字节数据
FileOutputStream fos = new FileOutputStream("pw2.txt",true);
//转换输出流(是一个高级流,且是一个字符流)。1:衔接字符与字节流 2:将写出的字符转换为字节
OutputStreamWriter osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8);
//缓冲输出流(是一个高级流,且是一个字符流)。块写文本数据加速
BufferedWriter bw = new BufferedWriter(osw);
//具有自动行刷新的缓冲字符输出流
PrintWriter pw = new PrintWriter(bw); //完成简易记事本。控制台输入的每行字符串都按行写入文件。单独输入exit时退出。
Scanner scanner = new Scanner(System.in);
while(true){
String line = scanner.nextLine();
if("exit".equalsIgnoreCase(line)){
break;
}
pw.println(line);
}
pw.close();
}
}

PrintWriter的自动行刷新功能

如果实例化PW时第一个参数传入的是一个流,则此时可以再传入一个boolean型的参数,此值为true时就打开了自动行刷新功能。

即:

每当我们用PW的println方法写出一行字符串后会自动flush.

package io;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Scanner; /**
* 在流连接中使用PW
*/
public class PWDemo2 {
public static void main(String[] args) throws FileNotFoundException {
//文件字节输出流(是一个低级流),向文件中写入字节数据
FileOutputStream fos = new FileOutputStream("pw2.txt",true);
//转换输出流(是一个高级流,且是一个字符流)。1:衔接字符与字节流 2:将写出的字符转换为字节
OutputStreamWriter osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8);
//缓冲输出流(是一个高级流,且是一个字符流)。块写文本数据加速
BufferedWriter bw = new BufferedWriter(osw);
//具有自动行刷新的缓冲字符输出流
/*
PrintWriter提供的构造器中,当第一个参数为一个流时,就支持再传入一个boolean
型的参数表示是否自动行刷新。当该值为true时则打开了自动行刷新功能。这意味着
每当我们调用println方法后会自动flush一次。
*/
PrintWriter pw = new PrintWriter(bw,true); //完成简易记事本。控制台输入的每行字符串都按行写入文件。单独输入exit时退出。
Scanner scanner = new Scanner(System.in);
while(true){
String line = scanner.nextLine();
if("exit".equalsIgnoreCase(line)){
break;
}
pw.println(line);
}
pw.close();
}
}

总结

对象流

对象流是一对高级流,在流链接中的作用是完成对象的序列化反序列化

序列化:是对象输出流的工作,将一个对象按照其结构转换为一组字节的过程。

反序列化:是对象输入流的工作,将一组字节还原为对象的过程。

java.io.ObjectInputStream对象输入流,继承自java.io.InputStream

常用构造器

ObjectInputStream(InputStream in):创建一个对象输入流并连接到参数in这个输入流上。

常用方法

Object readObject():进行对象反序列化,将读取的字节转换为一个对象并以Object形式返回(多态)。

如果读取的字节表示的不是一个java对象会抛出异常:java.io.ClassNotFoundException

java.io.ObjectOutputStream对象输出流,继承自java.io.OutputStream

常用构造器

ObjectOutputStream(OutputStream out):创建一个对象输出流并连接到参数out这个输出流上

常用方法

void writeObject(Object obj):进行对象的序列化,将一个java对象序列化成一组字节后再通过连接的输出流将这组字节写出。

如果序列化的对象没有实现可序列化接口:java.io.Serializable就会抛出异常:java.io.NotSerializableException

序列化接口java.io.Serrializable

该接口没有任何抽象方法,但是只有实现了该接口的类的实例才能进行序列化与反序列化。

实现了序列化接口的类建议显示的定义常量:static final long serialVersionUID = 1L;

可以为属性添加关键字transient,被该关键字修饰的属性在序列化是会被忽略,达到对象序列化瘦身的目的。

day03 对象流与序列化的更多相关文章

  1. Java对象流与序列化学习

    对象流与序列化 对象流有两个类 ObjectOutputStream:将java对象的基本数据类型和图形写入OutputStream ObjectInputStream:对以前使用ObjectOutp ...

  2. 动车上的书摘-java对象流与序列化

    摘要: 摘要: 原创出处: http://www.cnblogs.com/Alandre/ 泥沙砖瓦浆木匠 希望转载,保留摘要,谢谢! 钢笔不限贵便宜,书法是来自心对手的交流.-泥沙砖瓦浆木匠 一.对 ...

  3. Java基础IO类之对象流与序列化

    对象流的两个类: ObjectOutputStream:将Java对象的基本数据类型和图形写入OutputStream ObjectInputStream:对以前使用ObjectOutputStrea ...

  4. java对象流与序列化

    Object流,直接把obj写入或读出. 前言: 比如 画图的程序,咣当画一个三角形出来,咣当画一正方形出来.然后存盘,当你下次再打开软件的时候三角形.方块还在原来的位置上.如果用面向对象的思维,三角 ...

  5. Java之IO流进阶篇:内存流,打印流,对象流

    Java中的IO流,即为输入输出流.所谓输入输出流,都是相对于程序而言,程序就是这个参照物.一张图看懂输入输出流: 输入流抽象基类:InputStream,Reader 输出流抽象基类:OutputS ...

  6. day010-缓冲流、转换流、序列化流

    1.     缓冲流 又称为高效流.高效流高效的原理:使用缓冲区(数组)临时存储多个数据,减少底层资源的调用次数.从而提高读写速度. 1.1 缓冲流分类 字节缓冲流: BufferedOutputSt ...

  7. java --对象流与对象的序列化

    对象流 ObjectInputStream ObjectOutputStream类分别是InputStream和OutputStream的子类,对象输出流使用writeObject(Object ob ...

  8. 用非常硬核的JAVA序列化手段实现对象流的持久化保存

    目录 背景 对象流的概念 对象流实例 引入一张组织结构图 定义组织架构图的类 类的完整结构 用对象流保存组织架构的对象信息 核心代码 用对象流读取文件并输出 核心代码 总结 背景 在OOP(面向对象编 ...

  9. 零基础学习java------day17------缓冲字节流,转换字节流,简化流,缓冲字符流,序列化和对象流

    1. 缓冲字节流 缓冲区:缓冲区实质上是一个数组.通常它是一个字节数组,但是也可以使用其他种类的数组.但是一个缓冲区不 仅仅 是一个数组.缓冲区提供了对数据的结构化访问,而且还可以跟踪系统的读/写进程 ...

随机推荐

  1. [AcWing 36] 合并两个排序的链表

    点击查看代码 /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * L ...

  2. Win10搭建Jenkins部署Java项目(本机和远程Win10部署)

    目录 一.前言&背景 二.环境准备 三.插件安装 四.全局配置 Maven JDK Git Maven 五.新建项目并配置 新建项目 配置 1.Discard old builds 2.Thi ...

  3. Nginx编译安装及常用命令

    一个执着于技术的公众号 前言 前面我们已经了解Nginx基础入门知识,今天就带大家一起学习下Nginx编译安装部署 准备工作 一台linux机器(本次实验以CentOS 7.5为例) 到Nginx官方 ...

  4. data structure assignment problem record

    Question1: Similar to pause command in linux read -n 1 Question2 read : Illegal option -n 原因为ubuntu ...

  5. webpack与vite的对比

    vite与webpack的打包原理: vite: 基于游览器原生ES Module,利用游览器解析import,服务器端按需编译返回 webpack: 逐级递归识别依赖,构建依赖图谱->转化AS ...

  6. vivo 万台规模 HDFS 集群升级 HDFS 3.x 实践

    vivo 互联网大数据团队-Lv Jia Hadoop 3.x的第一个稳定版本在2017年底就已经发布了,有很多重大的改进. 在HDFS方面,支持了Erasure Coding.More than 2 ...

  7. Flask_WTF实现表单

    Flask_WTF实现表单可分为六个步骤: ①导入FlaskForm扩展包(from flask_wtf import FlaskForm) ②导入StringField,PasswordField, ...

  8. C++:制作火把

    制作火把 时间限制 : 1.000 sec          内存限制 : 128 MB 题目描述: 小红最近在玩一个制作火把的游戏,一开始,小红手里有一根木棍,她希望能够通过这一根木棍通过交易换取制 ...

  9. 功耗优化之Sensor功耗分析

    功耗优化之Sensor功耗分析 一.Sensor功耗问题分类 二.Sensor功耗问题分析方法 SSC子系统引起系统无法进入AOSD问题分析: SSC子系统频繁唤醒AP问题分析方法 SSC子系统的GP ...

  10. call apply bind的作用及区别? 应用场景?

    call.apply.bind方法的作用和区别: 这三个方法的作用都是改变函数的执行上下文,换句话说就是改变函数体内部的this指向,以此来扩充函数依赖的作用域 1.call 作用:用于改变方法内部的 ...