对象流

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. 165. Compare Version Numbers - LeetCode

    Question 165. Compare Version Numbers Solution 题目大意: 比较版本号大小 思路: 根据逗号将版本号字符串转成数组,再比较每个数的大小 Java实现: p ...

  2. 第06组Alpha冲刺(6/6)

    目录 1.1 基本情况 1.2 冲刺概况汇报 1.郝雷明 2.曹兰英 3. 方梓涵 4.曾丽莉 5.鲍凌函 6.杜筱 7.黄少丹 8.詹鑫冰 9.董翔云 10.吴沅静 1.3 冲刺成果展示 1.1 基 ...

  3. 详解SQL操作的窗口函数

    摘要:窗口函数是聚集函数的延伸,是更高级的SQL语言操作,主要用于AP场景下对数据进行一些分析.汇总.排序的功能. 本文分享自华为云社区<GaussDB(DWS) SQL进阶之SQL操作之窗口函 ...

  4. resttemplate 请求方式详解

    get 普通请求: restemplate.getForEntity(url,String.class).getBody(); get 导出请求: restemplate.getForEntity(u ...

  5. 史上最全Spring Cloud Alibaba--Nacos教程(涵盖负载均衡、配置管理、多环境切换、配置共享/刷新、灰度、集群)

    能够实现Nacos安装 基于Nacos能实现应用负载均衡 能基于Nacos实现配置管理 配置管理 负载均衡 多环境切换 配置共享 配置刷新 灰度发布 掌握Nacos集群部署 1 Nacos安装 Nac ...

  6. Linux系列之安装JDK

    卸载open jdk #查看jdk [root@localhost tools]# rpm -qa | grep jdk java-1.8.0-openjdk-headless-1.8.0.65-3. ...

  7. NLog自定义Target之MQTT

    NLog是.Net中最流行的日志记录开源项目(之一),它灵活.免费.开源 官方支持文件.网络(Tcp.Udp).数据库.控制台等输出 社区支持Elastic.Seq等日志平台输出 实时日志需求 在工业 ...

  8. BUUCTF-神秘龙卷风

    神秘龙卷风 通过提示知道压缩包密码是四位纯数字,通过爆破得到 得到一串编码 看样子应该是brainfuck编码 flag{e4bbef8bdf9743f8bf5b727a9f6332a8}

  9. 记一次APP渗透登录验证绕过思路

    前言: 起初是抓包时候查看返回状态码不一致,所以觉得是否可以通过修改状态码来达到绕过的目的,但是拦截响应包再替换手速不够,技术大哥就去搜了下,找到了一个方法,可以自动替换响应包内容. 在偏下方一点的地 ...

  10. SAP OLE download to excel

    REPORT RSDEMO01 NO STANDARD PAGE HEADING. * this report demonstrates how to send some ABAP data to a ...