java 反序列化报错 提示:java.io.StreamCorruptedException 异常

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java 反序列化报错 提示:java.io.StreamCorruptedException 异常相关的知识,希望对你有一定的参考价值。

public void view()
// TODO Auto-generated method stub
System.out.println("请输入要操作的文件路径");
Scanner scan = new Scanner(System.in);
String fileUrl = scan.nextLine();
File file = new File(fileUrl);
impl emp = new impl();
if (file.exists())
System.out.println("该文件已经找到");
try
FileInputStream fis = new FileInputStream(file);
ObjectInputStream ois = new ObjectInputStream(fis);
while (ois.readObject() != null)
ArrayList<impl> arr = (ArrayList<impl>) ois.readObject();
for (int i = 0; i < arr.size(); i++)
System.out.println(arr.get(i).getName());
System.out.println(arr.get(i).getBirthDate());
System.out.println(arr.get(i).getCreateDate());


catch (FileNotFoundException e)
// TODO Auto-generated catch block
e.printStackTrace();
catch (IOException e)
// TODO Auto-generated catch block
e.printStackTrace();
catch (ClassNotFoundException e)
// TODO Auto-generated catch block
e.printStackTrace();




控制台中:
java.io.StreamCorruptedException
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at neu.impl.view(impl.java:109)
at neu.test.main(test.java:28)

感觉是你while语句那块的问题,while(ois.readObject() != null)这条语句表明从对象流中读取一个对象,此时对象流已经从文件中读取了字节序列并且创建了一个对象的实例。而你又在while语句中再次调用ois.readObject(),对象流会再次读取文件中的字节序列去反序列化对象,如果文件已经到了EOF,就会出现问题。感觉ObjectInputStream还是别用在while循环中 参考技术A 你确定你读的文件就是你序列化的文件? 参考技术B 把路径找对了 参考技术C 帮你顶下。

Android Parcelable反序列化报错笔记:java.lang.RuntimeException: Unmarshalling unknown type code at offset

Parcelable反序列化报错

事件背景

有个实体类,利用Parcelable序列化保存在了本地,在新版本上新增了一个字段后,反序列化取数据时,报错如下:

java.lang.RuntimeException: Parcel android.os.Parcel: Unmarshalling
unknown type code xx at offset xx

代码示意

// 旧版本数据结构
public class ParcelableObject implements Parcelable 

	private int i;
	private float f;

    public ParcelableObject() 
    


	// getter & setter

	@Override
    public int describeContents() 
        return 0;
    

    @Override
    public void writeToParcel(Parcel dest, int flags) 
        dest.writeInt(this.i);
        dest.writeFloat(this.f)
    

    protected ParcelableObject(Parcel in) 
        this.i = in.readInt();
        this.f = in.readFloat();
    

    public static final Creator<ParcelableObject> CREATOR = new Creator<ParcelableObject>() 
        @Override
        public ParcelableObject createFromParcel(Parcel source) 
            return new ParcelableObject(source);
        

        @Override
        public ParcelableObject[] newArray(int size) 
            return new ParcelableObject[size];
        
    ;


新版代码增加了一个newVar字段,同时按顺序加上了读写方法。

// 新的数据结构:同样代码做省略处理
public class ParcelableObject implements Parcelable 

	private int i;
	private float f;
	// 新增字段
	private int newVar;

    @Override
    public void writeToParcel(Parcel dest, int flags) 
        dest.writeInt(this.i);
        dest.writeFloat(this.f);
        dest.writeInt(newVar);
        
    

    protected ParcelableObject(Parcel in) 
        this.i = in.readInt();
        this.f = in.readFloat();
        try 
            // 防止旧版数据报错。
            this.newVar = in.readInt();
         catch(Exception e) 
            // 报错时的兜底默认值
        	this.newVar = defautltValue;
        	// 报错不在这里,上面渠道newVar数据!!!!!!!!!
        
    


即使如上所示,添加了保护代码,可以依然报错:
java.lang.RuntimeException: Parcel android.os.Parcel: Unmarshalling unknown type code xx at offset xx

报错原理

序列化数据是一段连续的内存地址,会按照每个数据所占的大小去内存中取值,newVar取到下一段内存中的int值,可是每次取值都会根据该数据类型的所占位数产生一次偏移,所以导致整体数据去不全,最后报错。

解决办法

将newVar用对象类包装,取值失败,进入异常捕获,会进入默认的兜底默认值赋值,并且重设偏移量回到原偏移量

// 新的数据结构:同样代码做省略处理
public class ParcelableObject implements Parcelable 

	private int i;
	private float f;
	// 新增字段利用对象包装
	private NewVarObj newVarWrapper;

    @Override
    public void writeToParcel(Parcel dest, int flags) 
        dest.writeInt(this.i);
        dest.writeFloat(this.f);
        dest.writeSerializable(newVarWrapper);
        
    

    protected ParcelableObject(Parcel in) 
        this.i = in.readInt();
        this.f = in.readFloat();
        // 记录当前偏移量
        int positionOffset = in.dataPosition();
        try 
            // 防止旧版数据报错。因为是取对象值,无法取到,进入异常捕获流程,进行默认赋值
            this.newVar = (NewVarObj) in.readSerializable();
         catch(Exception e) 
            // 报错时的兜底默认值
        	this.newVar = defautltValue;
        	// 将偏移量重设回去!!!!!!!!!
        	in.setDataPosition(positionOffset);
        
    



// 新字段包装类型
public class NewVarObj implements Serializable 

	private static final long serialVersionUID = -934758980857565111L;

	private int newVar;

	// getter & setter

以上是关于java 反序列化报错 提示:java.io.StreamCorruptedException 异常的主要内容,如果未能解决你的问题,请参考以下文章

Newtonsoft.Json反序列化(Deserialize)报错问题

Android Parcelable反序列化报错笔记:java.lang.RuntimeException: Unmarshalling unknown type code at offset

Android Parcelable反序列化报错笔记:java.lang.RuntimeException: Unmarshalling unknown type code at offset(代码片

API接收数据反序列化失败问题查找

反序列化报错回显

php unserialize()不能反序列化时怎么做才能不提示错误