new一个ObjectInputStream为什么会出现java.io.EOFException

news2024/11/18 20:33:42

一、举例代码

package com.softeem.wolf.homework06;

import java.io.*;

/**
 * Created by 苍狼
 * Time on 2023-05-24
 */
public class App {
    public static void main(String[] args) throws IOException {
        ObjectInputStream ois = null;
        ObjectOutputStream oos = null;
        ois = new ObjectInputStream(new FileInputStream("src\\com\\softeem\\wolf\\homework06\\student.txt"));
        oos = new ObjectOutputStream(new FileOutputStream("src\\com\\softeem\\wolf\\homework06\\student.txt"));
        
        Student student1 = new Student(1,"张三",'男');
        Student student2 = new Student(2, "李四",'女');

        try {
            oos.writeObject(student1);
            oos.writeObject(student2);
            oos.writeObject(null);
            oos.close();
        } catch (IOException ioException) {
            ioException.printStackTrace();
        }
        try {
            Object object;
            while((object=ois.readObject())!=null){
                System.out.println(object);
            }
            ois.close();
        } catch (IOException ioException) {
            ioException.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        try {
            ois.close();
        } catch (IOException ioException) {
            ioException.printStackTrace();
        }
    }
}

在src\\com\\softeem\\wolf\\homework06\\路径下新建一个student.txt文件,运行程序。

发现会出现EOFException异常。这是为什么呢?

二、分析原因

我们用debugs的形式一步一步分析原因。

异常信息显示ois = new ObjectInputStream(new FileInputStream("src\\com\\softeem\\wolf\\homework06\\student.txt"));出现问题,

我们点进去看一ObjectInputStream的构造器

public ObjectInputStream(InputStream in) throws IOException {
        verifySubclass();
        bin = new BlockDataInputStream(in);
        handles = new HandleTable(10);
        vlist = new ValidationList();
        enableOverride = false;
        readStreamHeader();
        bin.setBlockDataMode(true);
    }

发现这里会调用一个readStreamHeader()方法,获取文件中数据流的头,然后我们在点进去看看这个readStreamHeader()方法。

protected void readStreamHeader()
        throws IOException, StreamCorruptedException
    {
        short s0 = bin.readShort();
        short s1 = bin.readShort();
        if (s0 != STREAM_MAGIC || s1 != STREAM_VERSION) {
            throw new StreamCorruptedException(
                String.format("invalid stream header: %04X%04X", s0, s1));
        }
    }

这个方法调用了bin.readShort(),看看readShort()方法的源码。

public short readShort() throws IOException {
            if (!blkmode) {
                pos = 0;
                in.readFully(buf, 0, 2);
            } else if (end - pos < 2) {
                return din.readShort();
            }
            short v = Bits.getShort(buf, pos);
            pos += 2;
            return v;
        }

发现它会调用in.readFully(buf, 0,2)这个方法,接着去这个方法的源码下看看。

void readFully(byte[] b, int off, int len) throws IOException {
            int n = 0;
            while (n < len) {
                int count = read(b, off + n, len - n);
                if (count < 0) {
                    throw new EOFException();
                }
                n += count;
            }
        }

接着在这个方法中调用read(b, off+n, len-n), 我们来看看这个源码。

public int read(byte[] b, int off, int len) throws IOException {
            if (len == 0) {
                return 0;
            } else if (peekb < 0) {
                return in.read(b, off, len);
            } else {
                b[off++] = (byte) peekb;
                len--;
                peekb = -1;
                int n = in.read(b, off, len);
                return (n >= 0) ? (n + 1) : 1;
            }
        }

它会运行到renturn in.read(b, off, len); 我们接着点进去看这个源码。

public int read(byte b[], int off, int len) throws IOException {
        if (b == null) {
            throw new NullPointerException();
        } else if (off < 0 || len < 0 || len > b.length - off) {
            throw new IndexOutOfBoundsException();
        } else if (len == 0) {
            return 0;
        }

        int c = read();
        if (c == -1) {
            return -1;
        }
        b[off] = (byte)c;

        int i = 1;
        try {
            for (; i < len ; i++) {
                c = read();
                if (c == -1) {
                    break;
                }
                b[off + i] = (byte)c;
            }
        } catch (IOException ee) {
        }
        return i;
    }

这个方法最终返回的结果是-1;然后一直把结果往上传,传到readFully(byte[] b, int off, int len)方法进行判断,如果count<0,则抛出 EOFException异常。这就是new ObjectInputStream()对象的整个过程。

这个ObjectInputStream构造器中的readStreamHeader()方法就是获取文件头的流,但是由于我们这个student.txt文件是空的,所以获取不到文件头流,导致count为-1,从而出现EOFException异常。

三、解决办法

解决办法也很简单。只需要将new ObjectOutputStream()和new ObjectInputStream()顺序调换就行。

package com.softeem.wolf.homework06;

import java.io.*;

/**
 * Created by 苍狼
 * Time on 2023-05-24
 */
public class App {
    public static void main(String[] args) throws IOException {
        ObjectInputStream ois = null;
        ObjectOutputStream oos = null;
        oos = new ObjectOutputStream(new FileOutputStream("src\\com\\softeem\\wolf\\homework06\\student.txt"));
        ois = new ObjectInputStream(new FileInputStream("src\\com\\softeem\\wolf\\homework06\\student.txt"));
        Student student1 = new Student(1,"张三",'男');
        Student student2 = new Student(2, "李四",'女');

        try {
            oos.writeObject(student1);
            oos.writeObject(student2);
            oos.writeObject(null);
            oos.close();
        } catch (IOException ioException) {
            ioException.printStackTrace();
        }
        try {
            Object object;
            while((object=ois.readObject())!=null){
                System.out.println(object);
            }
            ois.close();
        } catch (IOException ioException) {
            ioException.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        try {
            ois.close();
        } catch (IOException ioException) {
            ioException.printStackTrace();
        }
    }
}

运行结果

因为oos = new ObjectOutputStream(new FileOutputStream("src\\com\\softeem\\wolf\\homework06\\student.txt"))在运行的时候,构造器中

writeStreamHeader()方法会将文件头写进去,这就可以避免ObjectInputStream()构造器在运行readStreamHeader()方法时检测不到文件头。

下面是ObjectOutputStream中构造器的源码。

public ObjectOutputStream(OutputStream out) throws IOException {
        verifySubclass();
        bout = new BlockDataOutputStream(out);
        handles = new HandleTable(10, (float) 3.00);
        subs = new ReplaceTable(10, (float) 3.00);
        enableOverride = false;
        writeStreamHeader();
        bout.setBlockDataMode(true);
        if (extendedDebugInfo) {
            debugInfoStack = new DebugTraceInfoStack();
        } else {
            debugInfoStack = null;
        }
    }

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

功率信号源的特点和用途是什么

功率信号源是一种电子测量仪器&#xff0c;它集信号发生器与功率放大器为一体&#xff0c;具有高电压、大功率的特点。在电子实验室中&#xff0c;功率信号源可以帮助用户驱动压电陶瓷、换能器以及电磁线圈等&#xff0c;有效地解决了驱动负载和放大功率的问题。下面我们来具体…

Linux:LAMP的架构与环境配置

这里写目录标题 一、LAMP1.1 LAMP是什么1.2 安装顺序 二、编译安装Apache httpd服务2.1 关闭防火墙&#xff0c;将安装Apache所需软件包传到/opt目录下2.2 安装环境依赖包2.3 配置软件模块2.4 编译及安装2.5 优化配置文件路径2.6 添加httpd系统服务2.7 修改httpd 服务配置文件2…

MySql基础学习(2)

MySql基础学习 一、函数1.1 字符串函数1.2 数值函数1.3 日期函数1.4 流程控制语句 二、约束2.1 约束基本分类2.2 外键约束2.3 删除/更新行为 三、多表查询3.1 多表关系3.2 多表查询概述3.3 多表查询分类3.3.1 内连接3.3.2 外连接3.3.3 连接查询-自连接 3.4 联合查询-union&…

[SpringBoot]xml写mapper

创建工程[SpringBoot框架]如何使用SpringBoot框架_万物更新_的博客-CSDN博客 实现步骤: 测试: <?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd…

Visual Studio || Visual Studio Code 连接 SQL Server 和 mysql

使用Visua Studio链接本地SQL Server和服务器上的mysql。 软件版本&#xff1a; Visual Studio 2022&#xff1b;Visual Studio Code 2023&#xff1b;SQL Server 2019mysql8.0 一、软件准备二、连接SQL Server2.1 使用Visual Studio 连接SQL Server2.2 使用VS Code连接SQL Ser…

【qemu】将vmdk转换为img镜像教程

qemu软件下载地址&#xff1a; 64位下载地址&#xff1a;QEMU for Windows – Installers (64 bit) 32位下载地址&#xff1a;QEMU for Windows – Installers (32 bit) 找到qemu的目录&#xff0c;然后使用cmd打开&#xff08;qemu软件没有封装exe包&#xff0c;所以只能用…

伺服系统使用S曲线

在之前文章《S形曲线规划方式汇总》 介绍过贝塞尔曲线方式&#xff0c;并且在Marlin开源工程中也有贝塞尔曲线步进系统的实现方式。本篇介绍伺服系统中基于时间分割法实现的贝塞尔S曲线。 1 贝塞尔曲线路程规划 上文中推导过贝塞尔曲线&#xff0c;本文直接用结论&#xff1a…

分享一下如何使用echarts绘制散点图

文章目录 散点图源码地址 散点图 今天我来分享一下如何使用echarts绘制散点图 首先&#xff0c;我们需要引入echarts库。可以通过以下代码在HTML文件中引入&#xff1a; <script src"https://cdn.jsdelivr.net/npm/echarts5.2.0/dist/echarts.min.js"></s…

整合SSM(Spring + SpringMVC + Mybatis)

7、整合SSM 7.1、环境要求7.2、数据库环境7.3、基本环境搭建7.4、Mybatis层编写7.5、Spring层7.6、SpringMVC层7.7、小结及展望 7.1、环境要求 环境&#xff1a; IDEA MySQL 5.7.19 Tomcat 9 Maven 3.6 要求&#xff1a; 需要熟练掌握MySQL数据库&#xff0c;Spring&#…

FMT ICF5实时仿真,不止于飞控

基于ICF5的实时仿真 作为FMT的首款自研的国产开源飞控硬件平台&#xff0c;ICF5不仅功能强大&#xff0c;而且高颜值和高性价比获得了用户的一致好评。 FMT ICF5飞控 ICF5购买链接​item.taobao.com/item.htm?id705459383848&ali_refida3_430620_1006:1123834906:N:O3mc…

常见的主流自动化测试框架,这5种真的帮助巨大

今天我们要向大家介绍的是常见5种主流自动化测试框架&#xff0c;包括优缺点等内容&#xff0c;供大家参考学习。 1.ATF 自动化测试框架AutoTestFramework是B/S架构框架&#xff0c;可实现Selenium等多种自动化测试全流程、团队化管理的高级框架平台&#xff0c;通过集成自动化…

Zookeeper+消息队列Kafka

一、Zookeeper 概述 官方下载地址&#xff1a;Index of /dist/zookeeper 1.1 Zookeeper 定义 Zookeeper是一个开源的分布式的&#xff0c;为分布式框架提供协调服务的Apache项目。 1.2 Zookeeper 工作机制 Zookeeper从设计模式角度来理解&#xff1a;是一个基于观察者模式设…

PyCharm配置Opencv(多人亲测可用)

23/5/29更新&#xff1a; 之前由于只安装opencv-python-contrib这个包&#xff0c;导致Opencv版本过高&#xff0c;有些算法无法使用&#xff0c; 所以这里更新安装opencv-contrib-python这个包&#xff0c;具体如下配置。 ————————————————————————…

【C++】map和set的使用及其模拟实现

文章目录 一、map和set的使用1. 关联式容器2. 键值对3. 关联式容器的使用3.1 set3.2 multiset3.3 map3.4 multimap 二、map和set的模拟实现1. 红黑树的实现(封装map和set版本)1.1 节点的实现1.2 KeyOfT(仿函数)1.3 红黑树的插入Insert1.4 迭代器iterator 2. set的模拟实现3. ma…

【分布式】分片存储服务器

完成了配置路由服务器之后&#xff0c;我们来到了对存储服务器的重构 在我们加入配置服务器组之后&#xff0c;我们发现我们的kvserver&#xff0c;也就是存储服务器还是单点的&#xff1a; 同样&#xff0c;我们可以借助之前实现的raft对单点进行拓展&#xff0c;我们可以设置…

【LeetCode热题100】打卡第7天:盛最多水的容器

文章目录 盛最多水的容器⛅前言&#x1f512;题目&#x1f511;题解 盛最多水的容器 ⛅前言 大家好&#xff0c;我是知识汲取者&#xff0c;欢迎来到我的LeetCode热题100刷题专栏&#xff01; 精选 100 道力扣&#xff08;LeetCode&#xff09;上最热门的题目&#xff0c;适合…

自制Arduino 风格开发板 - HK32F030MF4P6 紧凑开发板

模仿Arduino Nano 做一个HK32F030M 的紧凑开发板&#xff0c;排针间距和Arduino Nano 相同&#xff0c;整体尺寸略小&#xff0c;适合插在面包板上。兼容HK32F030MF4P6 和0301M&#xff0c;板载CH340N 串口和DS1307 时钟模块。开源工程地址&#xff1a;HK32F030MF4P6 紧凑开发板…

Python学习36:文本分析与加密

类型&#xff1a;字符串‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬ 描述‪‬‪…

测试百科:白盒测试用例的设计

正文 语句覆盖&#xff1a;每条语句至少执行一次。判定覆盖&#xff1a;每个判定的所有可能结果至少出现一次。&#xff08;又称“分支覆盖”&#xff09;条件覆盖&#xff1a;每个条件的所有可能结果至少执行一次。判定/条件覆盖&#xff1a;一个判定中的每个条件的所有可能结…

PyTorch-网络模型的保存和读取

1. 模型的保存 方法一&#xff1a;保存模型的结构模型的参数 陷阱&#xff1a;需要让文件访问到你自己的模型定义方式&#xff0c;可以用import的方式引入先前的模型定义。 model_save.py import torch import torchvisionvgg16 torchvision.models.vgg16(weightsNone) # …