Kryo сериализация/десериализация

Я пытаюсь использовать крио для сериализации и десериализации в двоичный код. Я думаю, что у меня работает сериализация, но я не могу десериализовать. Ниже приведен код, с которым я возился, но в конечном итоге я хочу сохранить byte[] и позже прочитать его снова. В документации показано только, как это сделать с файлами.

        Kryo kryo = new Kryo();
        kryo.register(ArrayList.class);
        kryo.register(Modifier.class);

        ByteArrayOutputStream b = new ByteArrayOutputStream();

        Modifier modifier = new Modifier();
        modifier.type = "Yo swa!";
        modifier.amount = 10;

        Output output = new Output(b);
        kryo.writeClassAndObject(output, modifier);

        System.out.println("Kryo size: " + output.toBytes().length);

        Input input = new Input(output.getBuffer());

        //Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 11, Size: 0
        Modifier r = kryo.readObject(input, Modifier.class);
        //Same error:
        Modifier r = kryo.readObject(new Input(new ByteArrayInputStream(output.toBytes())), Modifier.class);

        System.out.println(r.type);

person Madmenyo    schedule 18.09.2015    source источник
comment
Я думаю, вам нужно где-то указать размер в байтах, как если бы вы выделяли массив. Что такое b?   -  person Dici    schedule 18.09.2015
comment
@Dici ByteArrayOutputStream. Если я устанавливаю входной поток, скажем, byte[100], я получаю Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -2 в той же строке.   -  person Madmenyo    schedule 18.09.2015
comment
Вы должны использовать toBytes вместо getBuffer (см. документ javadox.com/com.esotericsoftware.kryo/kryo/2.23.0/com/), но я не думаю, что это является причиной вашей проблемы. . Что отображается вашим первым println ?   -  person Dici    schedule 18.09.2015
comment
@dici размер массива (13). Может ли это быть правильным? Класс, который я сериализую, содержит еще один тип int.   -  person Madmenyo    schedule 18.09.2015
comment
@dici Я изменил строку ошибки на эту: Modifier r = kryo.readObject(new Input(new ByteArrayInputStream(output.toBytes())), Modifier.class); все еще та же ошибка ..   -  person Madmenyo    schedule 18.09.2015
comment
Вы используете writeClassAndObject, но читаете с readObject. Вы должны писать с writeObject или читать с readClassAndObject   -  person Dici    schedule 18.09.2015
comment
@Dici Да, это оно. Я все время думал, что делаю что-то не так до этой строчки. Довольно мило, я попытался сериализовать с помощью java и получил 280 байт. Kryo сокращает его для меня до 23 байт, я думаю, это нормально для хранения в моей БД. Спасибо!   -  person Madmenyo    schedule 18.09.2015
comment
Я не знал, что Kryo так сильно сжимает. Я знаю, что это быстрее и гибче (не нужно помечать все классы как Serializable, имеет сериализаторы по умолчанию для тривиальных объектов данных и т. д.)   -  person Dici    schedule 19.09.2015
comment
@Dici Я думаю, это потому, что он не сериализует класс или, скорее, хранит эту информацию где-то еще с .register. Так что ему нужно только то, что в нем. А null Integer — это всего лишь 1 байт, кто бы мог подумать? :D   -  person Madmenyo    schedule 19.09.2015


Ответы (1)


Вы сериализуете методом writeClassAndObject и десериализуете методом readObject, которые несовместимы.

Вы должны использовать либо writeClassAndObject => readClassAndObject, либо writeObject => readObject.

У меня работает следующее (kryo версии 2.21).

writeObject =>readObject

package test;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;

public class TestMain {

    public static void main(String[] args) {
        Kryo kryo = new Kryo();
        kryo.register(ArrayList.class);
        kryo.register(Modifier.class);

        ByteArrayOutputStream b = new ByteArrayOutputStream();

        Modifier modifier = new Modifier();
        modifier.type = "Yo swa!";
        modifier.amount = 10;

        Output output = new Output(b);
        kryo.writeObject(output, modifier);
        output.flush();
        output.close();

        System.out.println("Kryo size: " + output.toBytes().length);

        Input input = new Input(output.getBuffer());

        Modifier r = kryo.readObject(input, Modifier.class);

        System.out.println(r.type);
    }

    static class Modifier {
        String type;
        int amount;
    }
}

writeClassAndObject => readClassAndObject

package test;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;

public class TestMain {

    public static void main(String[] args) {
        Kryo kryo = new Kryo();
        kryo.register(ArrayList.class);
        kryo.register(Modifier.class);

        ByteArrayOutputStream b = new ByteArrayOutputStream();

        Modifier modifier = new Modifier();
        modifier.type = "Yo swa!";
        modifier.amount = 10;

        Output output = new Output(b);
        kryo.writeClassAndObject(output, modifier);
        output.flush();
        output.close();

        System.out.println("Kryo size: " + output.toBytes().length);

        Input input = new Input(output.getBuffer());

        Modifier r = (Modifier) kryo.readClassAndObject(input);

        System.out.println(r.type);
    }

    static class Modifier {
        String type;
        int amount;
    }
}
person David Hruby    schedule 31.07.2016