Методы сериализации String

 
 
 
Сообщения:78
Прив. Вот пишу сериализатор общий для C# и Java. Пока что разбираюсь с некоторыми базовыми типами, и столкнулся с проблемой сериализации класса String. Получается так, что в C# и в Java оно сериализуется по-разному.
Держите весь код
public enum MyEnum {
    EnumElement1(0),
    EnumElement2(1),
    EnumElement3(2);

    int id;

    MyEnum(int id)
    {
        this.id=id;
    }

    int getId()
    {
        return id;
    }
}

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;


public class Message {
    private int id;
    private double id1;
    private float id2;
    private String data;
    private ArrayList<Integer> list;
    private float[] fArray;
    private MyEnum enumEl;

    public Message(int id, double id1, float id2, String data)
    {
        this.id = id;
        this.id1 = id1;
        this.id2 = id2;
        this.data = data;
        list=new ArrayList<Integer>();
        list.add(1);
        list.add(2);
        list.add(3);
        fArray=new float[]{1.25f,2.036f,4.14f};
        enumEl = MyEnum.EnumElement2;
    }

    public Message(byte[] data) throws Exception
    {
        ByteArrayInputStream bais = new ByteArrayInputStream(data);
        DataInputStream dis = new DataInputStream(bais);

        Class cls =  this.getClass();
        Field[] fields = cls.getDeclaredFields();
        for(Field field : fields)
        {
            Class<?> type = field.getType();
            field.setAccessible(true);
            if(type==ArrayList.class)
            {
                ParameterizedType genType = (ParameterizedType)field.getGenericType();
                Class<?> argType = (Class<?>)genType.getActualTypeArguments()[0];
                int size = dis.readInt();
                if(argType==Integer.class)
                {
                    ArrayList<Integer> list = new ArrayList<Integer>();
                    for(int i =0; i<size; i++)
                    {
                        list.add(dis.readInt());
                    }
                    field.set(this,list);
                }

            }
            if(type.isArray())
            {
                if(type.getComponentType()==float.class)
                {
                    int length = dis.readInt();
                    float[] fArray = new float[length];
                    for(int i =0; i<fArray.length; i++)
                    {
                        fArray[i]=dis.readFloat();
                    }
                    field.set(this,fArray);
                }
            }

            if(type.isEnum())
            {
                if(type==MyEnum.class)
                {
                    MyEnum myEnum = MyEnum.values()[dis.readInt()];
                    field.set(this,myEnum);
                }
            }

            if(type==float.class)
            {
                field.set(this, dis.readFloat());
            }

            if(type==int.class)
            {
                field.set(this, dis.readInt());
            }

            if(type==String.class)
            {
                field.set(this, dis.readUTF());
            }

            if(type==double.class)
            {
                field.set(this,dis.readDouble());
            }
        }
        dis.close();
    }

    public byte[] Serialize() throws Exception
    {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        DataOutputStream dos = new DataOutputStream(baos);

        Class cls =  this.getClass();
        Field[] fields = cls.getDeclaredFields();
        for(Field field : fields)
        {
            Class<?> type = field.getType();
            field.setAccessible(true);
            if(type==ArrayList.class)
            {
                ParameterizedType genType = (ParameterizedType)field.getGenericType();
                Class<?> argType = (Class<?>)genType.getActualTypeArguments()[0];
                if(argType==Integer.class)
                {
                    ArrayList<Integer> list =(ArrayList<Integer>) field.get(this);
                    dos.writeInt(list.size());
                    for(int i : list)
                    {
                        dos.writeInt(i);
                    }
                }
                System.out.println("After "+type+": "+dos.size());
            }
            if(type.isArray())
            {
                if(type.getComponentType()==float.class)
                {
                    float[] fArray = (float[])field.get(this);
                    dos.writeInt(fArray.length);
                    for(int i =0; i<fArray.length; i++)
                    {
                        dos.writeFloat(fArray[i]);
                    }
                }
                System.out.println("After "+type+": "+dos.size());
            }

            if(type.isEnum())
            {
                if(type==MyEnum.class)
                {
                    MyEnum myEnum = (MyEnum)field.get(this);
                    dos.writeInt(myEnum.getId());
                    System.out.println("After "+type+": "+dos.size());
                }
            }

            if(type==float.class)
            {
                dos.writeFloat((Float)field.get(this));
                System.out.println("After "+type+": "+dos.size());
            }

            if(type==int.class)
            {
                dos.writeInt((Integer)field.get(this));
                System.out.println("After "+type+": "+dos.size());
            }

            if(type==String.class)
            {
                dos.writeUTF((String)field.get(this));
                System.out.println("After " + type + ": " + dos.size());
            }

            if(type==double.class)
            {
                dos.writeDouble((Double)field.get(this));
                System.out.println("After "+type+": "+dos.size());
            }
        }
        dos.close();
        return baos.toByteArray();
    }

    public void Display() throws Exception
    {
        Class cls =  this.getClass();
        Field[] fields = cls.getDeclaredFields();
        for(Field field : fields)
        {
            Class<?> type = field.getType();
            field.setAccessible(true);
            System.out.println("Name: "+field.getName()+"  Type: "+type+"  Value: "+field.get(this));
            if(type== ArrayList.class)
            {
                ParameterizedType genType = (ParameterizedType)field.getGenericType();
                Class<?> argType = (Class<?>)genType.getActualTypeArguments()[0];
                if(argType==Integer.class)
                {
                    ArrayList<Integer> list =(ArrayList<Integer>) field.get(this);
                    for(int i : list)
                    {
                        System.out.println(i);
                    }
                }
            }
            if(type.isArray())
            {
                if(type.getComponentType()==float.class)
                {
                    float[] fArray = (float[])field.get(this);
                    for(int i =0; i<fArray.length; i++)
                    {
                        System.out.println(fArray[i]);
                    }
                }
            }

            if(type.isEnum())
            {
                if(type==MyEnum.class)
                {
                    MyEnum myEnum = (MyEnum)field.get(this);
                    System.out.println(myEnum);
                }
            }
        }
    }
}


public class Main {
    public static void main(String[] args) throws Exception{
        Message msg = new Message(1,2.0,3.56f,"hello world");
        msg.Serialize();
    }
}

Как видите, строку я сериализую при помощи
  DataOutputStream.writeUTF()

И строка вида "hello world" занимает 13 байт. Но ведь в ней всего 11 знаков, и еще 1 байт должен занимать знак конца строки, и того 12 байт должно быть. В C# все как раз так, строка занимает 12 байт.
Вот, посмотрите на вывод метода Serialize()
Для C#

Для Java
After int: 4
After double: 12
After float: 16
After class java.lang.String: 29
After class java.util.ArrayList: 45
After class [F: 61
After class MyEnum: 65

Почему так?
 
 
Сообщения:78
ну я уже типа разобрался, там нету никакого символа окончания строки. Просто вначале записывается длина последующих данных, так вот в Java эта длина состоит из двух байтов и пишется при помощи writeShort, а вот в C# это 1 байт в какой-то непонятной кодировке UTF7
 
 
Сообщения:78
то есть наоборот
upd: то есть нет, или да, в общем, я запутался, и решил сам писать отдельно длину и данные, только длина теперь в int, и вроде все нормально, а еще я заменил BAIS и DIS на ByteBuffer, потому что еще нужно было сделать .order(ByteOrder.Little_Endian), или как-то так
Изменен:01 фев 2015 20:31
 
 
Сообщения:7989
Это вы этим занялись потому что жсон не смогли заюзать что ли?

В общем виде писать сериализацию достаточно насосно и мучительно - там потихоньку всякие неприятные кейсы возникать будут... Так что если вы это делаете для развлечения - это одно. А если для реального проекта - то зря вы это затеяли, имхо.

www.codeabbey.com - programming problems for novice coders (+ certificates)
 
 
Сообщения:78
RodionGork:
Это вы этим занялись потому что жсон не смогли заюзать что ли?

В общем виде писать сериализацию достаточно насосно и мучительно - там потихоньку всякие неприятные кейсы возникать будут... Так что если вы это делаете для развлечения - это одно. А если для реального проекта - то зря вы это затеяли, имхо.

Да простой жсон меня не устраивает, а бинарный фиг гдей найдешь нормальный, там, походу, каждая его реализация сделана каким-то другим чуваком, в которую он влепил всякие свои костыли, что делает все это дело тупо несовместимым.
И че это за кейсы? Вот я запилил уже "развлекаясь" сериализатор для базовых типов, в том числе для массивов и списков. Нужно лишь определится, что List на C# - это ArrayList на Java, ну и в таком духе. А вот сегодня еще допишу такую штуку, чтобы можно было сериализовать экземпляры других классов.
Чому вы пугаете меня?????
 
 
Сообщения:7989
Quote:
Да простой жсон меня не устраивает

Я так и не понял чем не устраивает :-o

Вы ж сказали у вас там считанное число байт переслать надо всего...

Quote:
И че это за кейсы?

Ну всякое фуфло с дочерними классами, типы полей несовпадающие и т.п.

Quote:
Нужно лишь определится, что List на C# - это ArrayList на Java, ну и в таком духе

Т.е. если вы попытаетесь десериализовать в объект у которого поле имеет тип LinkedList - у вас оно не сработает что ли?

Или у вас можно только со специального вида объектами работать будет? Тогда это вроде не произвольная сериализация а достаточно кастомная. Но тогда уж лучше вообще сделать заточенную под приложение, обработать только несколько нужных типов и не париться.

Quote:
Чому вы пугаете меня

Да на кой мне вас пугать? :D

Просто имхо лучше сначала проект запилить на той сериализации какая есть, а дальше если она вас будет не устраивать - переделаете как считаете нужным. А так заранее тратить время на то что м.б. и не слишком-то актуально окажется - это только у себя же время отнимать...

www.codeabbey.com - programming problems for novice coders (+ certificates)
 
 
Сообщения:78
RodionGork:
Quote:
Да простой жсон меня не устраивает

Я так и не понял чем не устраивает :-o

Вы ж сказали у вас там считанное число байт переслать надо всего...

Quote:
И че это за кейсы?

Ну всякое фуфло с дочерними классами, типы полей несовпадающие и т.п.

Quote:
Нужно лишь определится, что List на C# - это ArrayList на Java, ну и в таком духе

Т.е. если вы попытаетесь десериализовать в объект у которого поле имеет тип LinkedList - у вас оно не сработает что ли?

Или у вас можно только со специального вида объектами работать будет? Тогда это вроде не произвольная сериализация а достаточно кастомная. Но тогда уж лучше вообще сделать заточенную под приложение, обработать только несколько нужных типов и не париться.

Quote:
Чому вы пугаете меня

Да на кой мне вас пугать? :D

Просто имхо лучше сначала проект запилить на той сериализации какая есть, а дальше если она вас будет не устраивать - переделаете как считаете нужным. А так заранее тратить время на то что м.б. и не слишком-то актуально окажется - это только у себя же время отнимать...

Меня уже не устраивается жсоновская, она человекочитаемая, а еще!.. а еще все равно придется искать все эти библиотеки, ой.
И я как раз таки кастомную и делаю, я же для себя её делаю, а я знаю, какие типы буду использовать и т.д.
 
 
Сообщения:7989
Quote:
а еще все равно придется искать все эти библиотеки, ой.

т.е. всё дело в том что вам maven / nuget не освоить что ли? :-o

я думал вы уже разобрались с ними и у вас оно работало...

А если потом библиотеки ещё для чего-нить понадобятся. Или вам самому этот же код в другом проекте будет нужен - вы его копировать что ли станете?

Ну впрочем развлекайтесь на здоровье - энтузиазма и потенциала-то у вас хватает :)

Я просто помню что недавно писал сериализацию в хм... Bencode (кста м.б. вам этот формат заюзать?) - ну это тестовое задание было. Так я часов 10 угрохал по-моему чтоб напилить что-то упрощённый jackson напоминающее, т.е. чтоб произвольные типы туда-обратно можно было сохранять... В общем не самое приятное занятие по моим ощущениям :(

Поэтому мне и кажется что м.б. не оч рационально тратить силы на это дело... Мороки много, а насколько это нужно - вопрос который вам ещё предстоит выяснить...

www.codeabbey.com - programming problems for novice coders (+ certificates)
Изменен:02 фев 2015 13:34
 
 
Сообщения:78
В моем случае мороки немного. Все те библиотеки имеют кучу излишеств, которые мне ни к чему. Вот как доделаю, код выложу, и если вы скажете, что там все фигня и оно вообще никуда не годится, то буду юзать уже че-то другое.
 
 
Сообщения:78
короче, я решил сначала запилить тот класс на c#, и в процессе решил попрокрастинировать. Создал темку про все это на другом форуме, и там мне снова начали говорить, что мол нужно JSON юзать, ибо будет лучше так.
Ну в итоге я разобрался с теми ошибками, которые были при использовании BSON, и сейчас уже все работает гладко, так что мой крутой сериализатор отменяется.
 
Модераторы:Нет
Сейчас эту тему просматривают:Нет