javaIO流(2)

一.字符流

字符流对数据的操作是以一个个字符为单位的,字符流只能读文本文件,并将读到的字节按照编码表转为对应的字符,Reader和Writer是字符流的两个最大的抽象类,InputStreamReader和OutputStreamWriter分别继承了Reader和Writer,它俩的功能就是将读取到的字节转换为字符,所以又被称为转换流

1. FileReader和FileWriter读写文件

FileReader常用方法方法阐述
FileReader(String fileName)构造方法,用来指定要读的文件
int read()读取一个字符,返回读到的字符的码值,如果读到-1则表示读取完毕
int read(char[] chars)一次读一个字符数组,返回实际读取到的字符个数

FileWriter常用方法方法阐述
FileWriter(String fileName,boolean append)构造方法,用来指定要写入的文件,并且可以设置是追加,还是覆盖当前内容
void writer(int c)一次写一个字符
void writer(char[] chars,in off,int len)一次写一个字符数组,从字符数组的off位置开始,写len个

1.1  一个字符一个字符读

public class CharDemo1 {
    public static void main(String[] args) throws IOException {

        /*
        字符流只能读文本文件,会将读到字节结合编码表转换为一个字符编码
         */

        //一次读一个字符

        FileReader fileReader = new FileReader("E:/demo.txt");
        FileWriter fileWriter = new FileWriter("E:/demo1.txt");
        int c = 0;
        while((c = fileReader.read())!=-1){
            fileWriter.write(c);
        }
        fileReader.close();
        fileWriter.close();
    }
}

1.2  一次读一个字符数组

public class CharDemo2 {
    public static void main(String[] args) throws IOException {


        /*
        字符流只能读文本文件,会将读到字节结合编码表转换为一个字符编码
         */


        //一次读一个char数组
        FileReader fileReader = new FileReader("E:/demo.txt");
        FileWriter fileWriter = new FileWriter("E:/demo1.txt");
        int size = 0;
        char[] chars = new char[10];
        while((size = fileReader.read(chars))!=-1){
            fileWriter.write(chars,0,size);
        }
        fileReader.close();
        fileWriter.close();
    }
}

2. 字符缓冲流(包装流)

BufferedReader常用方法方法阐述
BufferedReader(Reader in)构造方法,可以传入一个Reader类对象
String readLine()一次读一行数据

BufferedWrite常用方法方法阐述
BufferedWriter(Writer our)构造方法,可以传一个Writer类对象
void write(String s)一次写一个字符串
void newLine()写一个换行符

2.1 BufferedReader和BufferedWriter读写文件

BufferReader和BufferWriter是两个包装流,可以对节点流FileReader和FileWriter进行包装,支持一次读写一行数据大大提高了数据的读写效率,FileWriter的构造方法中可以增加一个布尔类型的参数,表示写入文件的内容不会覆盖原内容,而是追加到文件原有内容的后面,bufferWriter中的newLine()方法表示写入一个换行符到文件中

public class CharDemo3 {
    /*
    字符流只能读文本文件,会将读到字节结合编码表转为一个字符编码
     */

    public static void main(String[] args) throws IOException {
        FileReader fileReader = new FileReader("E:/demo.txt");
        FileWriter fileWriter = new FileWriter("E:/demo1.txt",true);//保留原来的内容,在原内容基础上向后追加(续写)
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
        String s = null;
        while((s=bufferedReader.readLine())!=null){
            bufferedWriter.write(s);
            bufferedWriter.newLine();//插入换行符
        }
        bufferedReader.close();
        bufferedWriter.close();
    }
}

2.2  BufferReader从控制台读取数据

public class CharDemo4 {
    public static void main(String[] args) throws IOException {
        /*
          利用BufferReader从控制台读取内容
     */

        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        System.out.println("请输入字符串");
        String s = bufferedReader.readLine();
        System.out.println(s);
    }

}

二.  对象输入输出字节流

对象输入流(ObjectInputStream):从文件中把对象输入到程序中

对象输出流(ObjectOutputStream):把java中的对象输出到文件中

这两个属于包装流,可以对字节输入流和字节输出流进行包装处理

1. 为什么要把对象输入到文件中

这是因为我们在程序中new的对象都存在内存中,当程序运行结束后,对象会随着销毁,无法做到将对象的信息永久保存,但有时我们有这种将对象信息永久保存的需求,在需要的时候在还原到程序中.

例如:平时一个游戏凌晨更新维护的时候,往往需要关闭服务器,那我们玩家的账号信息肯定要保存下来,等到维护完成,再将数据恢复到相应的玩家账号中

2. 对象的序列化和反序列化

对象的序列化:将对象信息从程序写到文件中保存

对象的反序列化:将对象信息从文件读到程序中

对象的序列化通过对象输出流来实现(ObjectOutputStream)

ObjectOutputStream常用方法方法阐述
ObjectOutputStream(OutputStream out)构造方法,传入一个字节输出流对象
writeObject(Object obj)将一个对象信息写入文件中

对象的反序列化通过对象输入流来实现(ObjectInputStream)

ObjectInputStream常用方法方法阐述
ObjectInputStream(InputStream in)构造方法,传入一个字节输入流对象
Object readObject(Object obj)从文件中读一个对象信息,并返回该对象

由Object readObject(Object obj)看出,字节输入流也是创建对象的一种方式

import java.io.Serializable;

/*
如果一个类需要被序列化到文件中,那么这个类就需要实现Serializable接口,实现后,会自动的为该类生成一个序列化编号
编号是类的唯一标识

但是自动生成的编号在类信息改变后,会重新为类生成一个编号

可以在类中显示的生成一个编号,这样类信息修改后,也不会改变
 */

public class Student implements Serializable {

    private static final long serialVersionUID = 771652260758459933L; //类的序列化编号
    private int num;

    private String name;

    @Override
    public String toString() {
        return "Student{" +
                "num=" + num +
                ", name='" + name + '\'' +
                '}';
    }

    public Student(int num, String name) {
        this.num = num;
        this.name = name;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
public static void main(String[] args) throws IOException, ClassNotFoundException {

        //当一个类的对象需要被序列化到文件时,这个类必须要生成一个序列化编号
        Student student = new Student(100,"jim");

        //对象序列化
        FileOutputStream fileOutputStream = new FileOutputStream("E:/demo.txt");
        ObjectOutputStream outputStream = new ObjectOutputStream(fileOutputStream);
        outputStream.writeObject(student);
        outputStream.close();

        //对象的反序列化
        FileInputStream fileInputStream = new FileInputStream("E:/demo.txt");
        ObjectInputStream inputStream = new ObjectInputStream(fileInputStream);
        Student stu = (Student)inputStream.readObject();
        System.out.println(stu);
        inputStream.close();
    }
}

 

自定义一个学生类,要想通过对象输入输出流对自定义的类进行序列化和反序列化,就必须实现Serializable接口,实现这个接口的类默认会生成一个序列化编号,这个编号就相当于一个身份证号一样,若类发生改变会重新生成一个序列化编号,当我们从文件中读取对象信息时,就是通过这个序列化编号去寻找是哪一个类的对象.

正因为类发生变化,序列化编号也会跟着变化,那么如果我们需要修改类信息时,下一次就无法完成反序列化, 因为编译器会拿着这次修改的编号去文件中找,但是文件中还存储的是上一次序列化时产生的编号,显然两次编号不同,编译器会认为这不是同一个类,即不是我们要反序列化的类,就会报错

解决方法:

显示生成序列化编号,这样对于这个类来说,无论怎么修改,它的序列化编号都不发生改变,但切记修改类信息后需要重新序列化对象,否则反序列化的扔是上次未修改的对象

3. IDEA设置序列化编号提示

 

注意这是新版IDEA的操作,设置好后点击OK即可,这样在自定义的类中如果实现了Serializable接口,鼠标放到类名上就会显示

 

此时编译器就会自动生成一个序列化编号,这样无论怎么修改类信息,在对象进行序列化和反序列化时都不会报错,唯一需要注意的是,如果修改了类的信息,需要自己重新将对象序列化一次,才是修改后的对象信息,否则还是保存的上一次未修改的对象的信息

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【大模型LLM面试合集】大语言模型基础_NLP面试题

NLP面试题 1.BERT 1.1 基础知识 BERT(Bidirectional Encoder Representations from Transformers)是谷歌提出,作为一个Word2Vec的替代者,其在NLP领域的11个方向大幅刷新了精度,可以说是近年来自残差网络最优突破性的…

流程图编辑框架LogicFlow-vue-ts和js

LogicFlow官网https://site.logic-flow.cn/LogicFlow 是一款流程图编辑框架,提供了一系列流程图交互、编辑所必需的功能和灵活的节点自定义、插件等拓展机制。LogicFlow支持前端研发自定义开发各种逻辑编排场景,如流程图、ER图、BPMN流程等。在工作审批配…

数据结构/作业/2024/7/7

搭建个场景: 将学生的信息,以顺序表的方式存储(堆区),并且实现封装函数︰1】顺序表的创建, 2】判满、 3】判空、 4】往顺序表里增加学生、5】遍历、 6】任意位置插入学生、7】任意位置删除学生、8】修改、 9】查找(按学生的学号查…

不同层数PCB如何选择合适板厚?

在回答这个问题前,我们首先需要了解什么是PCB厚度。 PCB厚度是指电路板完成后的厚度。 覆铜板的厚度:0.5、0.7、0.8、1.0、1.2、1.5、1.6、2.0、2.4、3.2和6.4毫米。 纸基覆铜板的标称厚度为 0.7 至 1.5 毫米。让我们开始了解更多细节。 标准 PCB 铜厚度…

使用GZip对npm run build打包的vendor.js文件进行压缩

vue-cli项目 安装npm i compression-webpack-plugin -D npm i compression-webpack-plugin -D使用:在vue.config.js文件中 const CompressionPlugin require(compression-webpack-plugin) module.exports {configureWebpack: {plugins: [new CompressionPlugin…

北斗在高铁轨道位移监测中的应用

随着高速铁路的飞速发展,轨道的监测与维护变得至关重要。传统的监测方法已难以满足现代高铁的需求。 近年来,北斗卫星导航系统凭借其高精度、全天候、全球覆盖的优势,在高铁轨道位移监测中发挥了重要作用。 高铁轨道监测系统通过集成北斗卫星…

谷歌正在试行人脸识别办公室安全系统

内容提要: 🧿据美国消费者新闻与商业频道 CNBC 获悉,谷歌正在为其企业园区安全测试面部追踪技术。 🧿测试最初在华盛顿州柯克兰的一间办公室进行。 🧿一份内部文件称,谷歌的安全和弹性服务 (GSRS) 团队将…

C/C++ 代码注释规范及 doxygen 工具

参考 谷歌项目风格指南——注释 C doxygen 风格注释示例 ubuntu20 中 doxygen 文档生成 doxygen 官方文档 在 /Doxygen/Special Command/ 章节介绍 doxygen 的关键字 注释说明 注释的目的是提高代码的可读性与可维护性。 C 风格注释 // 单行注释/* 多行注释 */ C 风格注…

Git注释规范

主打一个有用 代码的提交规范参考如下: init:初始化项目feat:新功能(feature)fix:修补bugdocs:文档(documentation)style:格式(不影响代码运行的变动)refactor:重构(即不是新增功能…

动手实操微软开源的GraphRAG

微软在今年4月份的时候提出了GraphRAG的概念,然后在上周开源了GraphRAG,Github链接见https://github.com/microsoft/graphrag,截止当前,已有6900Star。 安装教程 官方推荐使用Python3.10-3.12版本,我使用Python3.10版本安装时,在…

【C++】类和对象(中)--下篇

个人主页~ 类和对象上 类和对象中-上篇 类和对象 五、赋值运算符重载1、运算符重载2、赋值运算符重载3、前置和后置重载 六、const成员七、日期类的实现Date.hDate.cpptest.cpptest1测试结果test2测试结果test3测试结果test4测试结果test5测试结果test6测试结果test7测试结果 八…

如何在Excel中对一个或多个条件求和?

在Excel中,基于一个或多个条件的求和值是我们大多数人的常见任务,SUMIF函数可以帮助我们根据一个条件快速求和,而SUMIFS函数可以帮助我们对多个条件求和。 本文,我将描述如何在Excel中对一个或多个条件求和? 在Excel中…

R语言学习笔记2-RRStudio环境配置(Windows版)

R语言学习笔记2-R&RStudio环境配置(Windows版) 安装 R安装RStudio修改默认工作目录修改镜像验证镜像源修改文件编码 环境测试 安装 R R下载地址: https://mirrors.tuna.tsinghua.edu.cn/CRAN/bin/windows/base/ 点击下载链接并运行安装程…

《网络安全和信息化》是什么级别的期刊?是正规期刊吗?能评职称吗?

​问题解答 问:《网络安全和信息化》是不是核心期刊? 答:不是,是知网收录的正规学术期刊。 问:《网络安全和信息化》级别? 答:国家级。主管单位:工业和信息化部 主办单位&#…

PostgreSQL主从同步

目录 一、主从复制原理 二、配置主数据库 2.1 创建同步账号 2.2 配置同步账号访问控制 2.3 设置同步参数 3.4 重启主数据库 三、配置从数据库 3.1 停止从库 3.2 清空从库数据文件 3.3 拉取主库数据文件 3.4 配置从库同步参数 3.5 启动从库 四、测试主从 4.1在主库…

家用美容仪维修

美容仪行业是一个随着消费者对外貌和健康关注度不断提高而快速发展的行业。以下是对美容仪行业的详细分析: 一、行业概况 美容仪是一种根据人体生理机能进行调节改善身体和面部的机器,具有美白、嫩肤、祛斑、祛皱、脱毛、减肥等多种功能。随着科技的发…

Mac可以玩Steam吗?苹果电脑可以玩的单机游戏有哪些?

Mac可以玩Steam吗 关于Mac是否能够运行Steam这一问题,答案是肯定的。Steam平台已经支持Mac操作系统,玩家可以通过Steam在Mac上购买、下载和游玩各种优秀的游戏作品。不过,需要注意的是,并非所有的Steam游戏都有Mac版,…

JavaScript 中的面向对象编程--->构造函数--->原型对象与原型链,由浅入深详细讲解!

前言:哈喽,大家好,我是前端菜鸟的自我修养!今天给大家分享JavaScript 中的面向对象编程--->构造函数--->原型对象与原型链,由浅入深详细讲解!并提供具体代码帮助大家深入理解,彻底掌握&am…

去水印小程序源码修复版-前端后端内置接口+第三方接口

去水印小程序源码,前端后端,内置接口第三方接口, 修复数据库账号密码错误问题,内置接口支持替换第三方接口, 文件挺全的,可以添加流量主代码,搭建需要准备一台服务器,备案域名和http…

【Arduino】XIAOFEIYU(TM)实验ESP32使用DS18B20数字温度传感器模块(图文)

DS18B20 虽然具有测温系统简单、测温精度高、连接方便、占用口线少等优点。今天XIAOFEIYU(TM)就来实验一下使用ESP32连接DS18B20数字温度传感器模块。 DS18B20数字温度传感器模块一共有3个针脚,正负极加一个out数据接口。 连接传感器和ESP32组成测试电路&#xff1a…