Как разбить объект на байт []?

Как мне разбить объект - точнее, Parcelable; на самом деле это связка, но суть та же - в byte []? Я думал, что то, как я это делал, было хорошим решением, но, видимо, ошибался.

Просто для справки, вот старый способ, которым я это делал.

public static byte[] getBytes(Object obj) throws java.io.IOException {
    ByteArrayOutputStream bos   = new ByteArrayOutputStream();
    ObjectOutputStream oos      = new ObjectOutputStream(bos);
    oos.writeObject(obj);
    oos.flush();
    oos.close();
    bos.close();
    byte[] data = bos.toByteArray();
    return data;
}

Спасибо ~ Aedon

Изменить 1 ::

Нарушение такого объекта, как этот, передавая ему Bundle, вызывает NotSerializableException.


person ahodder    schedule 18.05.2011    source источник
comment
Вот как это сделать, в чем проблема? В любом случае, в большинстве случаев сериализация объекта - лучший обходной путь.   -  person dLobatog    schedule 19.05.2011
comment
Реализует ли ваш объект Serializable? Это могло быть ключом   -  person dLobatog    schedule 19.05.2011
comment
@eLobato Я не уверен, сериализуем ли Bundle. Но я так и думал.   -  person ahodder    schedule 19.05.2011


Ответы (3)


Ваш код выглядит в основном нормально. Я бы посоветовал следующее:

public static byte[] getBytes(Serializable obj) throws IOException {
    ByteArrayOutputStream bos   = new ByteArrayOutputStream();
    ObjectOutputStream oos      = new ObjectOutputStream(bos);
    oos.writeObject(obj);

    byte[] data = bos.toByteArray();

    oos.close();
    return data;
}
person aroth    schedule 18.05.2011
comment
Это определенно правильный способ сделать это. @Aedon - вы можете немного прочитать о сериализации и десериализации объектов, чтобы увидеть, попадете ли вы в какие-либо ловушки (статические атрибуты и т. Д.) - person Eric; 19.05.2011
comment
Ха! Спасибо, я даже не заметил, что закрываюсь до того, как дошел доByteArray. Я посмотрю, поможет ли это. Спасибо. - person ahodder; 19.05.2011
comment
Нет, я получаю NotSerializableException. Наверное, следовало добавить это к вопросу, мое плохое. Обновлено. - person ahodder; 19.05.2011
comment
@AedonEtLIRA - NotSerializableException означает, что объект, который вы пытаетесь сериализовать, не реализует интерфейс Serializable. Это означает, что вы не можете записать его напрямую, используя ObjectOutputStream. Вам нужно будет написать свой собственный код для сериализации объекта, скопировав любое интересующее вас состояние во что-то сериализуемое, например Map, или используя другие API для преобразования вашего конкретного типа объекта в байты. - person aroth; 20.05.2011

В вопросе упоминается Parcelable, который не всегда является сериализуемым. Я думаю, что правильным будет написать Parcelable в Parcel. Затем используйте метод marshall () Parcel для записи необработанных байтов.

Я немного поигрался с этим. Если ваш Parcelable следует протоколу, следующий код записывает правильный массив байтов для Parcelable. Предположим, что MyParcelable содержит 2 строки и одно целое число.

            Parcel parcel1 = Parcel.obtain();
            MyParcelable parcelable1 = new MyParcelable("a", "b", 25);
            parcelable1.writeToParcel(parcel1, 0);

            byte content[] = parcel1.marshall();
            parcel1.recycle();
            Parcel parcel2 = Parcel.obtain();
            parcel2.unmarshall(content, 0, content.length);
            parcel2.setDataPosition(0);
            MyParcelable parcelable2 = MyParcelable.CREATOR.createFromParcel(parcel2);
            parcel2.recycle();
            Toast.makeText(context, parcelable2.a + " " + parcelable2.b + " " + parcelable2.val, Toast.LENGTH_LONG).show();

Также см. Как использовать Parcel в Android?

person Alex Gitelman    schedule 19.05.2011
comment
@Alex Gitelman, не могли бы вы дать ссылку на документацию, о которой вы говорите, я хотел бы прочитать дальше. Что плохого в том, чтобы записать это на диск конкретнее. - person Nathan Schwermann; 19.05.2011
comment
@schwiz developer.android.com/reference/android/ os / предполагает, что этот механизм предназначен для IPC и его совместимость на разных платформах не гарантируется. Я думаю, что это должно быть приемлемо для краткосрочного хранения локально, но не для сетевых коммуникаций, например. В любом случае, я удалил свой код FileOutputStream, чтобы избежать путаницы. - person Alex Gitelman; 19.05.2011
comment
@Alex Gitelman, я только что прочитал документ о маршале. В нем говорится, что я не должен использовать данные покупателя в постоянном хранилище. Есть идеи, почему? Мне нужны данные для хранения в базе данных. - person ahodder; 19.05.2011
comment
@AedonEtLIRA Я думаю, что в документах говорится, что API-интерфейсы не пытаются обеспечить совместимость данных в разных версиях Android. Это означает, что если вы храните его в базе данных в течение длительного времени, а затем пользователь обновляет свое устройство, не гарантируется, что он будет правильно демаршалирован. То же самое, если вы хотите отправить его по сети на другое устройство. Итак, вам нужно определить ваш конкретный вариант использования. Если он вам нужен только для краткосрочного хранения, такого как кеширование или подобное, вероятно, все в порядке. Другими словами, если вам нужно прочитать его на том же устройстве в тот же день - это, вероятно, нормально. - person Alex Gitelman; 19.05.2011
comment
@Alex, ах. Хм. Тогда это не то, что мне нужно. Спасибо хоть. - person ahodder; 19.05.2011
comment
Вероятно, вам нужно будет сделать его сериализуемым, а затем следовать регулярной сериализации, как в исходном образце и другом ответе. Удачи! - person Alex Gitelman; 19.05.2011

Используйте библиотеку Okio, которая является удобной заменой ByteArrayOutputStream и имеет более мощный API.

public static byte[] getBytes(Serializable obj) throws IOException {
    Buffer buffer = new Buffer();
    ObjectOutputStream objectOut = new ObjectOutputStream(buffer.outputStream());
    objectOut.writeObject(obj);
    objectOut.close();
    return buffer.readByteArray();
}
person Evgeny Rogachev    schedule 23.04.2018