zoukankan      html  css  js  c++  java
  • java.io.StreamCorruptedException: invalid stream header: EFBFBDEF 问题解决

    错误方式

       @Test
        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);
        }
    正确方式
     @Test
        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);
        }

    原因是由于:

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

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

    测试代码 单元测试无法输出结果这里用main测试

     1 public static void main(String[] args) throws IOException {
     2         ByteArrayOutputStream baos = new ByteArrayOutputStream();
     3         ObjectOutputStream oos = new ObjectOutputStream(baos);
     4         String s = "111";
     5         oos.writeObject(s);
     6         String str = baos.toString(); 
     7         byte[] baStr = baos.toByteArray();
     8         byte[] gbStr = str.getBytes();
     9         byte[] testStr = baStr;
    10         StringBuffer sb = new StringBuffer();
    11         for (int i = 0; i < testStr.length; i++) {
    12             sb.append(Integer.toBinaryString(testStr[i]) + " ");
    13         }
    14         System.out.println(sb.toString());
    15     }

    1.如果将6行的str直接打印在页面上 则显示如下结果

     2.将第9行赋予baStr 则得到的二进制首两位值为

    11111111111111111111111110101100(0xac) 11111111111111111111111111101101(0xed)

    3.将第9行赋予gbStr 则得到的二进制首两位值为

    11111111111111111111111111101111(0xef) 11111111111111111111111110111111(0xbf)

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

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

    所以笔者建议:

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

    2.使用base64转换为字符串

    注:LZ出现这个问题是因为在maven打包项目的时候重新编译了项目中的二进制文件从而破坏了二进制文件的完整性。所以该文件无法反序列化。

    附: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>

     英文原文:

    http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4968673

    The provided test code serializes an object to a ByteArrayOutputStream, converts the generated byte array into a string using the ByteArrayOutputStream.toString() method, converts the string back into a byte array using the String.getBytes() method, and then attempts to deserialize the object from the byte array using a ByteArrayInputStream. This procedure will in most cases fail because of the transformations that take place within ByteArrayOutputStream.toString() and String.getBytes(): in order to convert the contained sequence of bytes into a string, ByteArrayOutputStream.toString() decodes the bytes according to the default charset in effect; similarly, in order to convert the string back into a sequence of bytes, String.getBytes() encodes the characters according to the default charset. Converting bytes into characters and back again according to a given charset is generally not an identity-preserving operation. As the javadoc for the String(byte[], int, int) constructor (which is called by ByteArrayOutputStream.toString()) states, "the behavior ... when the given bytes are not valid in the default charset is unspecified". In the test case provided, the first two bytes of the serialization stream, 0xac and 0xed (see java.io.ObjectStreamConstants.STREAM_MAGIC), both get mapped to the character '?' since they are not valid in the default charset (ISO646-US in the JDK I'm running). The two '?' characters are then mapped back to the byte sequence 0x3f 0x3f in the reconstructed data stream, which do not constitute a valid header. The solution, from the perspective of the test case, is to use ByteArrayOutputStream.toByteArray() instead of toString(), which will yield the raw byte sequence; this can then be fed directly to the ByteArrayInputStream(byte[]) constructor.

    原文地址 http://blog.sina.com.cn/s/blog_61f4999d0100yi89.html

  • 相关阅读:
    多功能回到顶部组件,速度可调控,带隐藏效果,返回过程中可回滚。
    可扩展进度条,商城常用!
    多功能万能模态框插件,项目实用,持续更新中...
    前端页面重构技巧总结TIP【持续更新...】
    微信小程序入门实例之记事本
    webpack1.x环境配置与打包基础【附带各种 "坑" 与解决方案!持续更新中...】
    CSS3利用背景渐变和background-size配合完成渐变与条纹效果[持续更新中...]
    CSS3利用一个div实现内圆角边框效果
    CSS3实现原腾讯视频透明边框,多重边框等(关于边框那些不为人知的事情)
    使用条件注释完成浏览器兼容
  • 原文地址:https://www.cnblogs.com/yanlong300/p/7692595.html
Copyright © 2011-2022 走看看