Модераторы: LSD, AntonSaburov

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Object -> byteStream, как из Serialized объекта получить набор 
V
    Опции темы
KOp4iK
Дата 2.10.2006, 16:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 118
Регистрация: 26.11.2004
Где: Латвия

Репутация: нет
Всего: 3



День добрый!

Есть система которая пересылает объект по сети
Код

        private ObjectOutputStream outputStream;
        outputStream.writeUnshared(object);

на другой стороне есть приёмник
Код

       private final ObjectInputStream inputStream;
       Object o = inputStream.readUnshared();

объекты конечно сереализованые. Всё работает... но в силу различных причин решили уйти от посылки целых объектов и посылать потоки битиков. Внимание вопрос как можно сделать преобразование object -> bytesArray -> Object 
Зарание спасибо
PM MAIL   Вверх
LSD
Дата 2.10.2006, 17:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 19
Всего: 538



Создайте свой интерфейс, где и определите методы toByteArray() и fromByteArray().


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
KOp4iK
Дата 3.10.2006, 10:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 118
Регистрация: 26.11.2004
Где: Латвия

Репутация: нет
Всего: 3



Цитата(LSD @ 2.10.2006,  17:03)
Создайте свой интерфейс, где и определите методы toByteArray() и fromByteArray().

но проблемма в том что сообщений тысячи... и в каждом рализовывать эти методы слишком долго... омжет есть какой более универсальный метод?
PM MAIL   Вверх
LSD
Дата 3.10.2006, 10:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 19
Всего: 538



Я не пойму что ты хочешь. Чем тебе не устраивает универсальная сериализация, и что значит посылать потоки битиков?
Объясни почетче.


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
KOp4iK
Дата 4.10.2006, 10:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 118
Регистрация: 26.11.2004
Где: Латвия

Репутация: нет
Всего: 3



Цитата(LSD @ 3.10.2006,  10:54)
Я не пойму что ты хочешь. Чем тебе не устраивает универсальная сериализация, и что значит посылать потоки битиков?
Объясни почетче.

Использовать не ObjectOutputStream и ObjectInputStream, а OutputStream и InputStream. Глобально проблемма в том, что мы используем Java IO (в которой и посылаем целые объекты), а в Java NIO на которую мы переходим нет (как мне известно) пересылки объектов... Вот и приходится, чтоб не переделывать все пересылаемые объекты, искать обходные пути. 
PM MAIL   Вверх
LSD
Дата 4.10.2006, 10:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 19
Всего: 538



1. ObjectOutputStream и ObjectInputStream - это классы которые просто переводят объект в двоичное представление им вообще все равно в какой именно поток им приходится писать. При желании можно сделать обертку и для ByteBuffer и писать в него.
2. NIO не самостоятельная библиотека, а расширение для IO. Тот же FileChannel не создашь без FileInputStream или FileOutputStream.
3. Использовать NIO как самоцель это не разумно. NIO надо использовать если есть проблемы с производительностью и узкое место ввод-вывод. Но это не тот случай, в данном случае "тормозить" будут ObjectOutputStream и ObjectInputStream, т.к. они работают через рефлексию. Если реально проблема с производительностью, то надо писать свои методы toByteBuffer() и fromByteBuffer() - это будет самым быстрым решением.


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
COVD
Дата 5.10.2006, 17:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 26.7.2005

Репутация: 11
Всего: 43



Если вы собираетесь использовать nio в неблокирующем режиме (а это и есть одно из преимуществ, позволяющее обслуживать много клиентов одним потоком), то вам предстоит решить еще одну проблему.  Чтобы успешно восстановить обьект из массива байтов, необходимо чтобы к этому моменту все байты были на месте, т.е. обьект полностью получен. Но байты передаются по сети порциями и в io необходимый механизм для этого есть. В nio же придется это делать руками. В общем случае, в принимаемом потоке байтов надо распознать начало обьекта, дождаться получения последнего байта обьекта и только после этого можно превратить полученную последовательность байт в обьект одним из перечисленных LSD методов. Весьма интересная задача smile.
PM MAIL   Вверх
KOp4iK
Дата 10.10.2006, 10:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 118
Регистрация: 26.11.2004
Где: Латвия

Репутация: нет
Всего: 3



Цитата

Если вы собираетесь использовать nio в неблокирующем режиме (а это и есть одно из преимуществ, позволяющее обслуживать много клиентов одним потоком), то вам предстоит решить еще одну проблему.  Чтобы успешно восстановить обьект из массива байтов, необходимо чтобы к этому моменту все байты были на месте, т.е. обьект полностью получен. Но байты передаются по сети порциями и в io необходимый механизм для этого есть. В nio же придется это делать руками. В общем случае, в принимаемом потоке байтов надо распознать начало обьекта, дождаться получения последнего байта обьекта и только после этого можно превратить полученную последовательность байт в обьект одним из перечисленных LSD методов. Весьма интересная задача .


ну звучит очень зловеще... с намёком на разложенные грабельки... Но пока я их(грабелек) не нашол!

Код

        boolean mayTry = false;
        do {
            mayTry = readLength();
            if (mayTry) {
                mayTry = readObject();
            }
        } while (mayTry);


смысл: Как только нам приходит что-то на приём выполняем этот кусочек. Вид потока байтов у нас: <objectLength1><object1><objectLength2><object2>... у и соответственно readLength() и readObject() возвращают "да" если удалось считать. Размер текущего сообщения мы всегда сонраняем в глобальную переменную...

Или я чего-то не понял?

PM MAIL   Вверх
KOp4iK
Дата 10.10.2006, 10:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 118
Регистрация: 26.11.2004
Где: Латвия

Репутация: нет
Всего: 3



Оказывается есть 2 возможности написать преобразование Object -> ByteArray -> Object

Я тут маленький примерчик навоял... 
Код

import java.io.*;
import java.util.Vector;

public class Test {
    public static void main(String[] args) {
        Vector o = new Vector();
        byte[] array = new byte[0];
        try {
            array = ObjectConverterStreamOld.fromObject(o);
            o = (Vector) ObjectConverterStreamOld.toObject(array);
        } catch (Exception e) {
            e.printStackTrace();
        }
        for (int a = 0; a < array.length; a++) {
            System.out.print(array[a] + "; ");
        }
        System.out.println();
        System.out.println("length - " + array.length);
// -----------------------------------------------------------------------------------------
        try {
                array = ObjectConverterClassLoaderOld.fromObject(o);
                o = (Vector) ObjectConverterClassLoaderOld.toObject(array);
        } catch (Exception e) {
            e.printStackTrace();
        }
        for (int a = 0; a < array.length; a++) {
            System.out.print(array[a] + "; ");
        }
        System.out.println();
        System.out.println("length - " + array.length);
    }
}

class ObjectConverterClassLoader {
    
    public static byte[] fromObject(Object o) throws IOException {
        ByteArrayOutputStream str = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream( str ) {
            protected void writeClassDescriptor( ObjectStreamClass desc ) throws IOException {
                writeUTF( desc.getName() );
            }
        };
        out.writeObject( o );
        out.flush();

        return str.toByteArray();
    }

    public static Object toObject(byte[] b) throws IOException, ClassNotFoundException {
        ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(b)) {
            protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException
            {
                String className = readUTF();
                Class clazz = Class.forName( className, true, Thread.currentThread().getContextClassLoader() );
                return ObjectStreamClass.lookup( clazz );
            }
        };
        return in.readObject();
    }
}

class ObjectConverterStream {

    public static byte[] fromObject(Object o) throws IOException {
        ByteArrayOutputStream str = new ByteArrayOutputStream();
        ObjectOutputStream ostr = new ObjectOutputStream(str);
        ostr.writeUnshared(o);
        return str.toByteArray();
    }

    public static Object toObject(byte[] b) throws IOException, ClassNotFoundException {
        ObjectInputStream s = new ObjectInputStream(new ByteArrayInputStream(b));
        return s.readUnshared();
    }
}

Если его запустить то он выведет н экран размеры массивов и их длины... 

По скорости они вроде одинаковые... Запускал я 100 000 раз
Код

            array = ObjectConverterStreamOld.fromObject(o);
            o = (Vector) ObjectConverterStreamOld.toObject(array);

и оба  варианта выполняли за 3 секунды... НО!!! интерестно почему масивы байтов в которые конвертиться один и тотже Vector разные при чём на 93 байта... 
А теперь внимание вопрос  smile 
1) Мож у кого есть мысли ПОЧЕМУ(разные размеры у массивов)?
2) Какой из двух конвертеров вам кажеться наиболее правильным? 
PM MAIL   Вверх
Guest
Дата 10.10.2006, 10:39 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Цитата

Или я чего-то не понял?


Правильно вы поняли. Сначала надо посылать размер обьекта в байтах, потом сам обьект. Размер обьекта в общем случае - это целое число, т.е. 4 байта. Чисто теоретически эти 4 байта тоже могут придти не сразу, а по частям smile
  Вверх
LSD
Дата 10.10.2006, 11:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 19
Всего: 538



Цитата(KOp4iK @  10.10.2006,  11:20 Найти цитируемый пост)
1) Мож у кого есть мысли ПОЧЕМУ(разные размеры у массивов)?

Потому что стандартный заголовок у сериализации другой (он больше).

Цитата(KOp4iK @  10.10.2006,  11:20 Найти цитируемый пост)
2) Какой из двух конвертеров вам кажеться наиболее правильным?

Тот который с использованием стандартного ObjectInputStream/ObjectOutputStream.


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
KOp4iK
Дата 10.10.2006, 11:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 118
Регистрация: 26.11.2004
Где: Латвия

Репутация: нет
Всего: 3



Цитата(LSD @ 10.10.2006,  11:15)
Цитата(KOp4iK @  10.10.2006,  11:20 Найти цитируемый пост)
1) Мож у кого есть мысли ПОЧЕМУ(разные размеры у массивов)?

Потому что стандартный заголовок у сериализации другой (он больше).

Цитата(KOp4iK @  10.10.2006,  11:20 Найти цитируемый пост)
2) Какой из двух конвертеров вам кажеться наиболее правильным?

Тот который с использованием стандартного ObjectInputStream/ObjectOutputStream.

Извиняюсь за такую настырность(уж очень многое зависит от этого) А ПОЧЕМУ ИМЕННО ЭТОТ?  smile 

т.е если оба гарантируют 100% конвертацию в обе стороны то мне кажеться очевиднее использовать тот при котором меньше надо по сети передавать... так как 1 Vector eto 93 байта а "5 старушек - рупь"  smile 

Это сообщение отредактировал(а) KOp4iK - 10.10.2006, 11:51
PM MAIL   Вверх
LSD
Дата 10.10.2006, 11:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 19
Всего: 538



Стандартные классы ObjectInputStream/ObjectOutputStream отлажены и проверены ни одним десятком пользователей. Плюс там записывается дополнительная информация которая обеспечивает проверку того, что классы на разных машинах будут идентичны. Помимо прочего там записывается версия протокола.
Без всего этого есть хороший шанс наступить на грабли когда система уже будет работать.


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
COVD
Дата 10.10.2006, 13:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 26.7.2005

Репутация: 11
Всего: 43



Цитата(KOp4iK @ 10.10.2006,  10:04)
Цитата

Если вы собираетесь использовать nio в неблокирующем режиме (а это и есть одно из преимуществ, позволяющее обслуживать много клиентов одним потоком), то вам предстоит решить еще одну проблему.  Чтобы успешно восстановить обьект из массива байтов, необходимо чтобы к этому моменту все байты были на месте, т.е. обьект полностью получен. Но байты передаются по сети порциями и в io необходимый механизм для этого есть. В nio же придется это делать руками. В общем случае, в принимаемом потоке байтов надо распознать начало обьекта, дождаться получения последнего байта обьекта и только после этого можно превратить полученную последовательность байт в обьект одним из перечисленных LSD методов. Весьма интересная задача .


ну звучит очень зловеще... с намёком на разложенные грабельки... Но пока я их(грабелек) не нашол!

Код

        boolean mayTry = false;
        do {
            mayTry = readLength();
            if (mayTry) {
                mayTry = readObject();
            }
        } while (mayTry);


смысл: Как только нам приходит что-то на приём выполняем этот кусочек. Вид потока байтов у нас: <objectLength1><object1><objectLength2><object2>... у и соответственно readLength() и readObject() возвращают "да" если удалось считать. Размер текущего сообщения мы всегда сонраняем в глобальную переменную...

Или я чего-то не понял?

Цитата

ну звучит очень зловеще... с намёком на разложенные грабельки... Но пока я их(грабелек) не нашол!


На самом деле ничего зловещего тут конечно нет. smile

Ваш поток байтов <objectLength1><object1><objectLength2><object2>...  может передаваться порциями, например так  
<objectLength1><object1><object..pause..Length2><object2>...  

Если вы одним потоком в неблокирующем режиме читаете , то будет так
<objectLength1><object1><object..pause - переход к чтению данных другого сокета..Length2><object2>...  и дочитывать продолжение поток сможет после того, как он обойдет все остальные сокеты . Так что класть размер в глобальную переменную врядли получится.

PM MAIL   Вверх
KOp4iK
Дата 11.10.2006, 11:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 118
Регистрация: 26.11.2004
Где: Латвия

Репутация: нет
Всего: 3



Цитата

Если вы одним потоком в неблокирующем режиме читаете , то будет так
<objectLength1><object1><object..pause - переход к чтению данных другого сокета..Length2><object2>...  и дочитывать продолжение поток сможет после того, как он обойдет все остальные сокеты . Так что класть размер в глобальную переменную врядли получится.


ну так мы эго с начала в буфер положим и как только считаем >= 4 байт только потом в переменную записывать будем... а пока 4 байта <objectLengthN> не получим readLength() всегда нет возвращать будет 
вроде так  smile

Добавлено @ 11:13 
Цитата(LSD @ 10.10.2006,  11:58)
Стандартные классы ObjectInputStream/ObjectOutputStream отлажены и проверены ни одним десятком пользователей. Плюс там записывается дополнительная информация которая обеспечивает проверку того, что классы на разных машинах будут идентичны. Помимо прочего там записывается версия протокола.
Без всего этого есть хороший шанс наступить на грабли когда система уже будет работать.

Большой пасиб за пояснения. Очн жаль что не получиться экономить smile 
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Работа с сетью | Следующая тема »


 




[ Время генерации скрипта: 0.0595 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.