【Java】I/O 流篇 —— 转换流与序列化流

目录

  • 转换流
    • 原理
    • InputStreamReader 转换输入流
      • 构造方法
      • 代码示例
    • OutputStreamWriter 转换输出流
      • 构造方法
      • 代码示例
    • 练习
  • 序列化流
    • 序列化流
    • 反序列化流
    • **serialVersionUID**
      • 基本概念
      • 作用
      • 使用方式
      • transient 关键字
      • 注意事项

转换流

原理

  1. 转换流属于字符流,是字符流和字节流之间的桥梁

  2. 原理图如下:

在这里插入图片描述

  1. 作用:

    • 可以根据字符集一次读取多个字节

    • 读取数据不会乱码

    • 指定字符集读写数据(JDK 11 之后有代替方法)

    • 字节流可以使用字符流中的方法

InputStreamReader 转换输入流

构造方法

  • InputStreamReader(InputStream in)

    • 功能:创建一个使用默认字符集的 InputStreamReader 对象。
  • InputStreamReader(InputStream in, String charsetName)

    • 功能:创建一个使用指定字符集的 InputStreamReader 对象。
  • InputStreamReader(InputStream in, Charset cs)

    • 功能:创建一个使用指定 Charset 对象的 InputStreamReader 对象。

代码示例

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;public class demo {public static void main(String[] args) throws IOException {// 创建一个使用默认字符集的 InputStreamReader 对象InputStreamReader isr = new InputStreamReader(new FileInputStream("aaa.txt"));int ch;while((ch = isr.read()) != -1) {System.out.print((char)ch);}// 创建一个使用指定字符集的 InputStreamReader 对象InputStreamReader isr = new InputStreamReader(new FileInputStream("aaa.txt"),"GBK");int ch;while((ch = isr.read()) != -1) {System.out.print((char)ch);}// 创建一个使用指定 `Charset` 对象的 InputStreamReader 对象InputStreamReader isr = new InputStreamReader(new FileInputStream("aaa.txt"),Charset.forName("UTF-8"));int ch;while((ch = isr.read()) != -1) {System.out.print((char)ch);}isr.close();}	
}

JDK 11 给出了以上方法的替代方法,可以直接使用 FileReader:

import java.io.FileReader;
import java.io.IOException;
import java.nio.charset.Charset;public class demo {public static void main(String[] args) throws IOException {FileReader fr = new FileReader("aaa.txt",Charset.forName("UTF-8"));int ch;while((ch = fr.read()) != -1) {System.out.println((char)ch);}fr.close();}	
}

OutputStreamWriter 转换输出流

构造方法

  • OutputStreamWriter(OutputStream out)

    • 功能:创建一个使用默认字符集的 OutputStreamWriter 对象。
  • OutputStreamWriter(OutputStream out, String charsetName)

    • 功能:创建一个使用指定字符集的 OutputStreamWriter 对象。
  • OutputStreamWriter(OutputStream out, Charset cs)

    • 功能:创建一个使用指定 Charset 对象的 OutputStreamWriter 对象。

代码示例

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;public class demo {public static void main(String[] args) throws IOException {// 创建一个使用默认字符集的 `OutputStreamWriter` 对象OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("bbb.txt"));osw.write("月色真美");// 创建一个使用指定字符集的 `OutputStreamWriter` 对象OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("bbb.txt"),"GBK");osw.write("月色真美");// 创建一个使用指定 `Charset` 对象的 `OutputStreamWriter` 对象OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("bbb.txt"),Charset.forName("UTF-8"));osw.write("月色真美");osw.close();}	
}

JDK 11 给出了以上方法的替代方法,可以直接使用 FileWriter:

import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.Charset;public class demo {public static void main(String[] args) throws IOException {FileWriter fw = new FileWriter("bbb.txt",Charset.forName("UTF-8"));fw.write("月色真美");fw.close();}	
}

练习

要求:利用字节流读取文件中的数据,每次读一整行,而且不能出现乱码

思路:

  1. 字节流读取中文会出现乱码,但是字符流不会
  2. 字节流没有 readLine 方法,但是缓冲流有

代码示例:

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;public class demo {public static void main(String[] args) throws IOException {FileInputStream fis = new FileInputStream("aaa.txt");InputStreamReader isr = new InputStreamReader(fis);BufferedReader br = new BufferedReader(isr);String str = br.readLine();System.out.println(str);br.close();}	
}

简化一下代码:

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;public class demo {public static void main(String[] args) throws IOException {BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("aaa.txt")));String str = br.readLine();System.out.println(str);br.close();}	
}

序列化流

序列化流

序列化流,又叫对象操作输出流,可以把 Java 中的对象写到本地文件中

构造方法:public ObjectOutputStream(OutputStream out) 把基本流包装成高级流

成员方法:public final void writeObject(Object obj) 把对象序列化(写出)到文件中

代码示例:

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;class Person implements Serializable{String name;int age;public Person(String name, int age) {this.name = name;this.age = age;}public void setName(String name) {this.name = name;}public String getName() {return this.name;}public void setAge(int age) {this.age = age;}public int getAge() {return this.age;}@Overridepublic String toString() {return "姓名:" + name + " 年龄:" + age;}public static void main(String[] args) throws IOException {Person person1 = new Person("张三", 25);ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("bbb.txt"));oos.writeObject(person1);oos.close();}
}

注意事项:

  1. 使用对象输出流将对象保存到文件时会出现 NotSerializableException 异常,需要让类实现 Serializable 接口
  2. Serializable 接口里面没有抽象方法,是标记型接口,一旦实现该接口就表示当前类可以被序列化

反序列化流

反序列化流,又叫对象操作输入流,可以把序列化到本地文件中的对象数据读取到程序中

构造方法:public ObjectInputStream(InputStream out) 把基本流包装成高级流

成员方法:public Object readObject() 把序列化到本地文件中的对象数据读取到程序中

代码示例:

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;public class demo {public static void main(String[] args) throws IOException, ClassNotFoundException {ObjectInputStream ois = new ObjectInputStream(new FileInputStream("bbb.txt"));Object o = ois.readObject();System.out.println(o);ois.close();}	
}

serialVersionUID

serialVersionUID 是 Java 中用于序列化和反序列化过程的一个重要的版本控制机制,下面从基本概念、作用、使用方式、默认生成规则等方面详细介绍。

基本概念

serialVersionUID 是一个序列化版本标识符,是一个 private static final long 类型的常量,它被用于 Serializable 接口的实现类中。当一个类实现了 Serializable 接口,意味着该类的对象可以被序列化(转换为字节流)和反序列化(从字节流恢复为对象),而 serialVersionUID 用于确保在反序列化时,加载的类与序列化时的类是兼容的。

作用

  1. 版本控制:在序列化对象时,该对象的 serialVersionUID 会被写入到序列化流中。在反序列化时,JVM 会将流中的 serialVersionUID 与本地类的 serialVersionUID 进行比较。如果两者相同,JVM 认为类的版本是兼容的,可以进行反序列化操作;如果不同,会抛出 InvalidClassException 异常,防止因类的版本不兼容而导致数据丢失或错误。
  2. 保证兼容性:当类的结构发生变化(如添加、删除或修改了类的字段、方法等)时,通过手动指定 serialVersionUID,可以在一定程度上控制类的兼容性。如果开发者认为类的变化不影响反序列化,可以保持 serialVersionUID 不变,这样即使类的定义有小改动,反序列化过程仍然可以正常进行。

使用方式

  1. 手动指定 serialVersionUID

    在实现 Serializable 接口的类中,手动定义一个 serialVersionUID 常量,示例如下:

    import java.io.Serializable;public class Person implements Serializable {// 手动指定 serialVersionUIDprivate static final long serialVersionUID = 123456789L;private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public int getAge() {return age;}
    }
    
  2. 自动生成 serialVersionUID

    大多数集成开发环境(IDE),如 IntelliJ IDEA、Eclipse 等,都提供了自动生成 serialVersionUID 的功能。以 IntelliJ IDEA 为例,当一个类实现了 Serializable 接口但未定义 serialVersionUID 时,IDE 会在类名旁边显示一个提示,点击提示即可自动生成 serialVersionUID

transient 关键字

如果一个对象中的某个成员变量的值不想被序列化,给该成员变量加 transient 关键字修饰,该关键字标记的成员变量不参与序列化过程

import java.io.*;class User implements Serializable {private String username;// 用 transient 修饰 password,使其不被序列化private transient String password; public User(String username, String password) {this.username = username;this.password = password;}public String getUsername() {return username;}public String getPassword() {return password;}public static void main(String[] args) throws IOException, ClassNotFoundException {User user = new User("testUser", "testPassword");ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user.ser"));oos.writeObject(user);ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user.ser"));User deserializedUser = (User) ois.readObject();System.out.println("Username: " + deserializedUser.getUsername());System.out.println("Password: " + deserializedUser.getPassword()); }
}

注意事项

  • 版本管理:当类的结构发生重大变化,可能影响反序列化结果时,应该更新 serialVersionUID,以避免旧版本的序列化数据被错误地反序列化。
  • 安全性serialVersionUID 常量应该声明为 private static final long,以确保其不可修改,并且在类的所有实例中保持一致。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/24705.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mac 版 本地部署deepseek ➕ RAGflow 知识库搭建流程分享(附问题解决方法)

安装: 1、首先按照此视频的流程一步一步进行安装:(macos版)ragflowdeepseek 私域知识库搭建流程分享_哔哩哔哩_bilibili 2、RAGflow 官网文档指南:https://ragflow.io 3、RAGflow 下载地址:https://github.com/infi…

计算机三级网络技术备考

#subtotal 1Mbps1024kb128KB12.8M/s #1024B1KB 1024KB1MB 1024MB1GB #路由器的5G信号和平常的波长不同(5G的穿墙性能差) #局域网LAN(一公里内——构成集线机、交换机、同轴电缆) #城域网MAN(几公里到几十公里——光…

IDEA 2024.1 最新永久可用(亲测有效)

今年idea发布了2024.1版本,这个版本带来了一系列令人兴奋的新功能和改进。最引人注目的是集成了更先进的 AI 助手,它现在能够提供更复杂的代码辅助功能,如代码自动补全、智能代码审查等,极大地提升了开发效率。此外,用…

30 分钟从零开始入门 CSS

前言 最近也是在复习,把之前没写的博客补起来,之前给大家介绍了 html,现在是 CSS 咯。 30分钟从零开始入门拿下 HTML_html教程-CSDN博客 一、CSS简介:给网页“化妆”的神器 CSS(层叠样式表)就像“化妆“&a…

Game Maker 0.11更新:构建社交竞速游戏并增强玩家互动

在这三部分系列中,我们将介绍如何实现Game Maker 0.11中一些最激动人心的新功能。 欢迎来到我们系列文章的第一篇,重点介绍了The Sandbox Game Maker 0.11更新中的新特性。 The Sandbox Game Maker 0.11是一个多功能工具,帮助创作者通过游戏…

软件供应链安全工具链研究系列——RASP自适应威胁免疫平台(上篇)

1.1 基本能力 RASP是一种安全防护技术,运行在程序执行期间,使程序能够自我监控和识别有害的输入和行为。也就是说一个程序如果注入或者引入了RASP技术,那么RASP就和这个程序融为一体,使应用程序具备了自我防护的能力,…

2024信息技术、信息安全、网络安全、数据安全等国家标准合集共125份。

2024信息技术、信息安全、网络安全、数据安全等国家标准合集,共125份。 一、2024信息技术标准(54份) GB_T 17966-2024 信息技术 微处理器系统 浮点运算.pdf GB_T 17969.8-2024 信息技术 对象标识符登记机构操作规程 第8部分:通用…

HTTP与网络安全

🍅 点击文末小卡片 ,免费获取网络安全全套资料,资料在手,涨薪更快 一、HTTPS和HTTP有怎样的区别呢?HTTPS HTTP SSL/TLS(SSL或者TLS) HTTP:应用层 SSL/TLS:协议中间层 …

ASP.NET Core 8.0学习笔记(二十八)——EFCore反向工程

一、什么是反向工程 1.原则:DBFirst 2.反向工程:根据数据库表来反向生成实体类 3.生成命令:Scaffold-DbContext ‘连接字符串’ 字符串示例: Server.;DatabaseDemo1;Trusted_Connectiontrue; MultipleActiveResultSets true;Tru…

Unity基础——资源导出分享为Unity Package

一.选中要打包的文件夹,右击,点击Exporting package 二.勾选 Include Dependencies,点击Export Include Dependencies:代表是否包含资源依赖的选项 三.选择保存的位置,即可生成Unity package 最终形成文件&#xff1a…

kafka-leader -1问题解决

一. 问题: 在 Kafka 中,leader -1 通常表示分区的领导者副本尚未被选举出来,或者在获取领导者信息时出现了问题。以下是可能导致出现 kafka leader -1 的一些常见原因及相关分析: 1. 副本同步问题: 在 Kafka 集群中&…

【Java企业生态系统的演进】从单体J2EE到云原生微服务

Java企业生态系统的演进:从单体J2EE到云原生微服务 目录标题 Java企业生态系统的演进:从单体J2EE到云原生微服务摘要1. 引言2. 整体框架演进:从原始Java到Spring Cloud2.1 原始Java阶段(1995-1999)2.2 J2EE阶段&#x…

内容中台的企业CMS架构是什么?

企业CMS模块化架构 现代企业内容管理系统的核心在于模块化架构设计,通过解耦内容生产、存储、发布等环节构建灵活的技术栈。动态/静态发布引擎整合技术使系统既能处理实时更新的产品文档,也能生成高并发的营销落地页,配合版本控制机制确保内…

Binder通信协议

目录 一,整体架构 二,Binder通信协议 三,binder驱动返回协议 四,请求binder驱动协议 一,整体架构 二,Binder通信协议 三,binder驱动返回协议 binder_driver_return_protocol共包含18个命令,分别是: 四&#xff0c…

react 中,使用antd layout布局中的sider 做sider的展开和收起功能

一 话不多说,先展示效果: 展开时: 收起时: 二、实现代码如下 react 文件 import React, {useState} from react; import {Layout} from antd; import styles from "./index.module.less"; // 这个是样式文件&#…

神经网络 - 激活函数(Sigmoid 型函数)

激活函数在神经元中非常重要的。为了增强网络的表示能力和学习能力,激活函数需要具备以下几点性质: (1) 连续并可导(允许少数点上不可导)的非线性函数。可导的激活函数可以直接利用数值优化的方法来学习网络参数. (2) 激活函数及其导函数要尽可能的简单&#xff0…

供应链管理系统--升鲜宝门店收银系统功能解析,登录、主界面、会员 UI 设计图(一)

供应链管理系统--升鲜宝门店收银系统功能解析,登录、主界面 会员 UI 设计图(一)

从零开始的网站搭建(以照片/文本/视频信息通信网站为例)

本文面向已经有一些编程基础(会至少一门编程语言,比如python),但是没有搭建过web应用的人群,会写得尽量细致。重点介绍流程和部署云端的步骤,具体javascript代码怎么写之类的,这里不会涉及。 搭…

三轴加速度推算姿态角的方法,理论分析和MATLAB例程

三轴加速度推算三轴姿态的方法与MATLAB代码实现 文章目录 基本原理与方法概述静态姿态解算(仅俯仰角与横滚角)扩展(融合陀螺仪与加速度计)MATLAB代码 例程四元数动态姿态解算(融合加速度与陀螺仪)注意事项与扩展基本原理与方法概述 三轴加速度计通过测量重力分量在载体坐…

2025最新Flask学习笔记(对照Django做解析)

前言:如果还没学Django的同学,可以看Django 教程 | 菜鸟教程,也可以忽略下文所提及的Django内容;另外,由于我们接手的项目大多都是前后端分离的项目,所以本文会跳过对模板的介绍,感兴趣的朋友可…