java.io.StreamCorruptedException: invalid stream header: EFBFBDEF 问题解决

原因是由于:

将字 ByteArrayOutputStream对象调用为toString转为为字符串时,会将 ObjectOutputStream对象放置在对象流头部的前两个字节(0xac)(0xed)序列化为两个“?”

当这个字符串使用getByte()时会将两个“?”变为(0x3f )(0x3f) 。然而这两个字符并不构成有效的对象流头。所以转化对象时候会失败。

错误方式:

public void testDeserializeTest() throws IOException, ClassNotFoundException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        BigInteger bi = new BigInteger("0");
        oos.writeObject(bi);
        String str = baos.toString();
        System.out.println(str);
        ObjectInputStream ois = new ObjectInputStream(
                new BufferedInputStream(new ByteArrayInputStream(str.getBytes())));
        Object obj = ois.readObject();
        assertEquals(obj.getClass().getName(), "java.math.BigInteger");
        assertEquals(((BigInteger) obj).intValue(), 0);
    }

正确方式:

 public void testDeserialize() throws IOException, ClassNotFoundException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        BigInteger bi = new BigInteger("0");
        oos.writeObject(bi);
        byte[] str = baos.toByteArray();
        ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(new ByteArrayInputStream(str)));
        Object obj = ois.readObject();
        assertNotNull(obj);
        assertEquals(obj.getClass().getName(), "java.math.BigInteger");
        assertEquals(((BigInteger) obj).intValue(), 0);
    }

main测试:

public static void main(String[] args) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        String s = "111";
        oos.writeObject(s);
        String str = baos.toString(); 
        System.out.println(str.toString()); // 打印
        byte[] baStr = baos.toByteArray();
        byte[] gbStr = str.getBytes();
        byte[] testStr = baStr;
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < testStr.length; i++) {
            sb.append(Integer.toBinaryString(testStr[i]) + " ");
        }
        System.out.println(sb.toString());
    }

1.如果将str直接打印在页面上 则显示结果是: ??

2.将baStr 则得到的二进制首两位值为

11111111111111111111111110101100(0xac) 11111111111111111111111111101101(0xed)

3.将gbStr 则得到的二进制首两位值为

11111111111111111111111111101111(0xef) 11111111111111111111111110111111(0xbf)

(由于字符集和英文原作者不一样所以解析出来的结果也不一样)

发现字符被改变了以至于ObjectOutputStream无法识别该字符数组所以抛出了java.io.StreamCorruptedException: invalid stream header: EFBFBDEF

所以笔者建议:

1.使用 toByteArray()代替toString() ,使用 ByteArrayInputStream(byte [])构造函数。

2.使用base64转换为字符串

附:maven打包跳过二进制文件

<plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <configuration>
                    <!-- 防止二进制文件被编译 -->
                    <nonFilteredFileExtensions>
                        <nonFilteredFileExtension>dat</nonFilteredFileExtension>
                        <nonFilteredFileExtension>swf</nonFilteredFileExtension>
                        <nonFilteredFileExtension>xml</nonFilteredFileExtension>
                    </nonFilteredFileExtensions>
                </configuration>
            </plugin>
</plugins>

最后附上对象序列化和反序列化方法:

public static byte[] serialise(Object obj){
   ObjectOutputStream os=null;
   ByteArrayOutputStream bos=null;
   try {
      bos=new ByteArrayOutputStream();
      os=new ObjectOutputStream(bos);
      os.writeObject(obj);
      byte[] bytes=bos.toByteArray();
      return bytes;
   } catch (Exception e) {
      e.printStackTrace();
   }
   return null;
}

public static Object unserialize(byte[] bytes){
   ByteArrayInputStream bin=null;
   try {
      bin=new ByteArrayInputStream(bytes);
      ObjectInputStream in=new ObjectInputStream(bin);
      return in.readObject();
   } catch (Exception e) {
      e.printStackTrace();
   }
   return null;
}

 

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值