Данные сериализации повреждены на ПК, но не на устройстве Android

Я разрабатываю кроссплатформенное приложение, которое работает как на ПК, так и на Android. Это приложение сериализует объекты и сохраняет их в файл на нашем сервере. У меня проблема в том, что когда я десериализую один из объектов на ПК, я получаю следующую ошибку:

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 (Samsung s5). Это совершенно сбивает меня с толку. Я сузил его до проблемы с платформой, так как я взял закодированную строку напрямую и декодировал ее на обоих устройствах, где ошибка появляется на ПК, а не на устройстве 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;
}

Кроме того, это кодировщик Base64 I использовать.


person eBehbahani    schedule 28.04.2014    source источник
comment
Dalvik по-прежнему вероятно не совместим с потоковой передачей JRE для ПК. Исходя из этого вопроса, почему бы не использовать JSON (или XML)?   -  person Elliott Frisch    schedule 28.04.2014
comment
Хм, я уже некоторое время использую кодировку base64, и у меня не было никаких проблем. Я мог бы попытаться изменить метод сериализации, но хотел бы избежать этого, если это возможно.   -  person eBehbahani    schedule 28.04.2014


Ответы (2)


Вы забыли преобразовать String в byte[], чтобы отменить неявное преобразование byte[] в String, которое происходит при выполнении new String(Base64Coder.encode(data)).

Попробуйте это вместо этого:

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));
person Emanuel Moecklin    schedule 28.04.2014
comment
Метод декодирования преобразует строку в массив символов (см. здесь: source- code.biz/base64coder/java/Base64Coder.java.txt). Этого достаточно? - person eBehbahani; 28.04.2014
comment
Ты прав. Я предполагал, что Base64Coder.encode вернет byte[], но он возвращает char[], поэтому то, что я предлагаю, определенно не нужно. Я бы проверил, идентичен ли Base64Coder.decode(encodedObject) на Android и ПК. Если они идентичны, то Эллиот Фриш, вероятно, прав. Если это не идентично, то у библиотеки Base64 есть некоторые недостатки, и я бы попытался переключиться, например, на Apache (commons.apache.org/proper/commons-codec). - person Emanuel Moecklin; 28.04.2014
comment
Другая возможность заключается в том, что encodedObject не идентичен, что означает, что загрузка объекта с сервера уже ошибочна. Если ни encodedObject, ни декодированная строка base 64 не отличаются, и вы абсолютно хотите придерживаться сериализации Java, вы можете сериализовать/десериализовать объекты вручную (используя методы readObject/writeObject). - person Emanuel Moecklin; 28.04.2014
comment
Закодированные объекты различаются на ПК и на Android, хотя объекты идентичны. - person eBehbahani; 28.04.2014
comment
закодированные объекты = encodedObject (параметр в stringToObject)? - person Emanuel Moecklin; 28.04.2014
comment
Да, параметр encodedObject отличается в обоих случаях. - person eBehbahani; 29.04.2014
comment
Это означает, что загрузка сериализованного объекта уже имеет проблему, и вы должны сначала изучить ее. - person Emanuel Moecklin; 29.04.2014

Проблема в том, что Android до версии 7.0 (API 24) использует реализацию Apache Harmony Java, формат сериализации объектов которого несовместим с "обычной" JRE.

Поскольку Android 7.0 использует OpenJDK и совместим.

Смотрите также:

person Ilya Shinkarenko    schedule 16.06.2017