当前位置: 首页 > news >正文

EOFException异常详解

  最近线上的系统被检测出有错误日志,领导让我检查下问题,我就顺便了解了下这个异常。

  了解一个类,当然是先去看他的API,EOFException的API如下:

  通过这个API,我们可以得出以下信息:

  • 这是一个IO异常的子类,名字也是END OF FILE的缩写,当然也表示流的末尾
  • 它在表明一个信息,流已经到末尾了,而大部分做法是以特殊值的形式返回给我们,而不是抛异常

  也就是说这个异常是被主动抛出来的,而不是底层或者编译器返回给我的,就像NullPointerException或IndexOutOfBoundsException一样。

  我们先来看InputStream,这个输入流,当读到了结尾会怎么样,看看API介绍:

  可以看到如果到达流的末尾,那么会返回-1,也就是说我们可以根据这个-1来判断是否到达流的末尾。

  同样的我们看一下输入流的包装类BufferedReader,它有一个读一行的方法:

 

  也可以发现当读到流的末尾,通过返回值null来告诉我们到达流的末尾了,也就是说通过返回一个不可能的值来表示到达流的末尾。

  那我们找一个EOFException的例子,在jdk类中就有一个,那就是ObjectInputStream,我写了一个测试代码,如下:

复制代码
package yiwangzhibujian.objectstream;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class ObjectStream {
public static void main(String[] args) throws Exception {
User user1
=new User("yiwangzhibujian",27);
User user2
=new User("laizhezhikezhui",24);

ByteArrayOutputStream bos
=new ByteArrayOutputStream();
ObjectOutputStream oos
=new ObjectOutputStream(bos);
oos.writeObject(user1);
oos.writeObject(user2);
oos.writeObject(
null);
byte[] data = bos.toByteArray();
ByteArrayInputStream bis
=new ByteArrayInputStream(data);
ObjectInputStream ois
=new ObjectInputStream(bis);

System.out.println(ois.readObject());
System.out.println(ois.readObject());
System.out.println(ois.readObject());
System.out.println(ois.readObject());
}
}
class User implements Serializable{
private static final long serialVersionUID = 1L;
public String name;
public int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "User [name=" + name + ", age=" + age + "]";
}
}
复制代码

  控制台输出结果为:

复制代码
User [name=yiwangzhibujian, age=27]
User [name=laizhezhikezhui, age=24]
null
Exception in thread "main" java.io.EOFException
at java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:
2608)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:
1319)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:
371)
at yiwangzhibujian.objectstream.ObjectStream.main(ObjectStream.java:
28)

复制代码

  可以感觉到EOFException的用意,因为我们可以往流中放入null值,所以我们没法找到一个不可能的值来表示到达流的末尾,所以只能通过抛异常的方式来告诉用户到达末尾了,相应的抛异常部分的源码如下:

复制代码
byte peekByte() throws IOException {
int val = peek();
if (val < 0) {
throw new EOFException();
}
return (byte) val;
}
复制代码

  也就是说,ObjectInputStream在读取具体的对象之前会优先读取一个标识符,它通过是否能读到符号来判断是否到达流的末尾,因为再底层的流会通过返回-1来表明,然后ObjectInputStream会根据标识符来判断读到的是什么类型,因为ObjectOutputStream 在写入内容的时候会这么做:

  所以说ObjectInputStream可以自己判断流是否到达末尾,但是它无法告诉我们,我们不能替代他们读取这个标记,不然ObjectInputStream将识别不了下一个内容的实际类型。

  所以呢,对于这种异常的一般解决方法就是,捕获,可以记录日志,也可以不做处理,捕获异常以后,把之前读到的数据进行后续的处理就可以了,因为那就是所以的数据。还有就是如果打算记录日志,不要把它的堆栈信息打印出来,容易给人以错觉。毕竟EOFException实质上只是一个消息而已。

  当然抛异常的做法还是有一些偏激,但是当ObjectInputStream在不知道读取对象数量的情况下,确实无法判断是否读完,除非你把之前写入对象流的数量记录下来。所以说出现这个异常时就认真分析一下,这个异常是不是代表一个信息。

 

  希望我对这个问题的理解,能帮助到遇到同样问题的人。

  

 

http://www.xdnf.cn/news/831385.html

相关文章:

  • 什么是多元统计分析
  • 远程控制软件PcAnyWhere教程图解
  • NVIDIA Jetson Xavier NX入门-镜像为jetpack4(3)——pytorch和torchvision安装
  • 自己动手解决HEAP: Free Heap block XXX modified at YYY after it was freed问题
  • metaRTC通用H264文件帧获取发送方法
  • mac开发环境——iterm2配置
  • 【干货】常用的7种数据分析方法,建议收藏
  • 动软代码生成器
  • Paragon Partition Manager 9.0 Professional管理磁盘分区
  • 逆向分析 工具、加壳、安全防护篇
  • 汇编跳转指令B、BL、BX、BLX 和 BXJ的区别
  • 使用jQuery Mobile实现页面跳转
  • JS:offsetWidth\offsetleft 等图文解释
  • SSH 命令的三种代理功能(-L/-R/-D)
  • GPS 0183协议GGA、GLL、GSA、GSV、RMC、VTG、ZDA、DTM
  • 软件绿色版和安装版的区别
  • 华为太极magisk安装教程_教程:如何升级太极内部的应用
  • 2023年七大最佳勒索软件解密工具
  • Windows Server2012 R2 安装 VMware tools
  • java.lang.NoClassDefFoundError与aspectjrt、aspectjweaver的联系
  • linux下llt测试技巧,HLT与LLT测试简介
  • 软件运维服务方案
  • Java程序员必读的10本书籍
  • 理想低通滤波器、Butterworth滤波器和高斯滤波器
  • 电脑病毒可以直接破坏硬件吗?23年前的CIH做到了
  • 一家全是学霸!王力宏的哥哥也是博士,近日获5000余万拨款用于这项研究
  • 什么是逆向工程?特点是?应用领域有哪些?
  • SVN服务器搭建
  • 浅谈.htaccess
  • Java中Map的 entrySet() 详解以及用法(四种遍历map的方式)