【问题标题】:Serialization data is corrupt on PC but not on Android device序列化数据在 PC 上已损坏,但在 Android 设备上未损坏
【发布时间】:2014-04-28 01:59:28
【问题描述】:

我正在开发一个可在 PC 和 Android 上运行的跨平台应用程序。这个应用程序序列化对象并将它们保存到我们服务器上的文件中。我遇到的问题是,当我反序列化 PC 上的一个对象时,出现以下错误:

java.io.StreamCorruptedException: invalid type code: 71
at java.io.ObjectInputStream.readString(ObjectInputStream.java:1646)
at java.io.ObjectInputStream.readEnum(ObjectInputStream.java:1736)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1990)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1915)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1798)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1990)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1915)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1798)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350)
at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1706)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1344)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)

但是,我可以成功地反序列化 Android 手机(三星 s5)上的对象。这完全让我感到困惑。我已将其缩小为平台问题,因为我直接获取了编码字符串并在两个设备上对其进行了解码,在 PC 上而不是 Android 设备上弹出错误。这向我表明,编码的字符串实际上并没有损坏。我错过了什么吗?任何建议,将不胜感激。

这是我用来序列化对象的代码:

public static String objectToString(Serializable object) {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    try {
        ObjectOutputStream obj = new ObjectOutputStream(out);
        obj.writeObject(object);
        byte[] data = out.toByteArray();
        obj.close();
        out.close();

        return new String(Base64Coder.encode(data));
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

public static Object stringToObject(String encodedObject) {
    try {
        ByteArrayInputStream bin = new ByteArrayInputStream(Base64Coder.decode(encodedObject));
        ObjectInputStream input = new ObjectInputStream(bin);
        try{
        return input.readObject();
        }finally{
            Gdx.app.log(TAG, "Input closed!");
            input.close();
            bin.close();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

另外,this 我使用的 Base64 编码器。

【问题讨论】:

  • Dalvik 仍然是probably 与 PC JRE 不兼容。从那个问题来看,为什么不使用 JSON(或 XML)?
  • 嗯,我使用 base64 编码已经有一段时间了,没有遇到任何问题。我可以尝试更改序列化方法,但如果可能的话,我想避免这样做。

标签: java android serialization


【解决方案1】:

您忘记将 String 转换为 byte[] 以反转执行 new String(Base64Coder.encode(data)) 时发生的隐式 byte[] 到 String 的转换。

试试这个:

public static Object stringToObject(String encodedObject) {
    try {
        byte[] byteArray = encodedObject.getBytes();
        ByteArrayInputStream bin = new ByteArrayInputStream(Base64Coder.decode(byteArray));

代替:

public static Object stringToObject(String encodedObject) {
    try {
        ByteArrayInputStream bin = new ByteArrayInputStream(Base64Coder.decode(encodedObject));

【讨论】:

  • decode 方法将字符串转换为 char 数组(参见此处:source-code.biz/base64coder/java/Base64Coder.java.txt)。够了吗?
  • 你是对的。我假设 Base64Coder.encode 会返回一个 byte[] 但它返回一个 char[] 所以我的建议绝对没有必要。我会检查 Base64Coder.decode(encodedObject) 在 Android 和 PC 上是否相同。如果它是相同的,那么 Elliott Frisch 可能是对的。如果它不相同,那么 Base64 库有一些缺陷,我会尝试切换到例如阿帕奇(commons.apache.org/proper/commons-codec)。
  • 另一种可能性是编码对象不完全相同,这意味着从服务器加载对象已经出错。如果编码对象和解码后的 base 64 字符串都不同,并且您绝对想坚持 Java 序列化,那么您可以手动序列化/反序列化对象(使用 readObject/writeObject 方法)。
  • PC 和 Android 上的编码对象不同,即使对象相同。
  • 编码对象 = encodedObject(stringToObject 中的参数)?
【解决方案2】:

问题是 Android 7.0 版本(API 24)使用 Apache Harmony Java 实现,该对象序列化格式与“常规”JRE 不兼容。

由于 Android 7.0 使用 OpenJDK 并且兼容。

另见:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-29
    • 1970-01-01
    • 2018-11-21
    • 2015-10-12
    • 2011-11-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多