Как мне маршалировать данные для потоковой передачи по протоколу TCP? - PullRequest
2 голосов
/ 09 февраля 2020

Итак, для домашнего задания у меня есть пример того, как собирать данные и разбирать их.

Структура, которую они нам дали, была следующей: Event - это интерфейс. Wireformat - это класс, который «наследует» событие. WireFormatWidget - это класс с реальным кодом, который имеет маршал и демаршал.

У меня есть отдельные потоки, которые обрабатывают отправку данных в байтовом массиве с использованием TCP.

У меня проблема в том, что когда Я создаю объект Wireformat. Я столкнулся с проблемой с потоком, пытающимся упорядочить данные.

Exception in thread "main" java.lang.NullPointerException
    at myhw.WriteFormatWidget.getBytes(WriteFormatWidget.java:38)

Структура интерфейса определяет данные как сообщение, тип сообщения как целое число, временную метку (что я предполагаю, это дата и getTime этой даты), и трекер. Я не уверен, что такое трекер.

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

WriteFormatWidget состоит из этого :

private int type;
private long timestamp;
private String identifier;
private int tracker;

Так что для моего wireformat я создал его как класс, который расширяет WireFormatWidget и реализует Event, потому что это был единственный способ, которым Eclipse не выдал ошибку или предложил изменить WireFormatWidget или Event.

Теперь, когда я жестко кодирую свой специфицированный c wireformat, я создаю его экземпляр, и кажется, что он не может вызвать getBytes () с жестко закодированными значениями, которые я использую для тех же переменных.

public class MyWireFormat extends WireFormatWidget implements Event {
    private String identifier = "here is my custom wireformat";
    ....

Когда я распечатать идентификатор в getBytes в WireFormatWidget, я получаю нулевое значение, а не ожидаемый идентификатор, который я жестко закодировал. Поэтому я не должен «наследовать» соответственно. Что я делаю не так?

РЕДАКТИРОВАТЬ: WireFormatWidget (дано)

public class WriteFormatWidget {
private int type;
private long timestamp;
private String identifier;
private int tracker;

    public byte[] getBytes() throws IOException {
        byte[] marshalledBytes = null;
        ByteArrayOutputStream baOutputStream = new ByteArrayOutputStream();
        DataOutputStream dout = new DataOutputStream(new BufferedOutputStream(baOutputStream));

        dout.writeInt(type);
        dout.writeLong(timestamp);

        System.out.println("getBytes using identifier: " + identifier);

        byte[] identifierBytes = identifier.getBytes();
        int elementLength = identifierBytes.length;
        dout.writeInt(elementLength);
        dout.write(identifierBytes);

        dout.writeInt(tracker);

        dout.flush();
        marshalledBytes = baOutputStream.toByteArray();

        baOutputStream.close();
        dout.close();

        return marshalledBytes;
    }
}

Я сэкономлю место, не публикуя демаршаллизирующую часть. Но это то же самое, только наоборот.

Проблема, с которой я сталкиваюсь, заключается в печати данных со стороны клиента в качестве доказательства того, что я отправляю заранее.

Так что я выполню простую проверить, как напечатать тип или распечатать идентификатор. Это терпит неудачу, и у меня есть ноль.

Ответы [ 2 ]

1 голос
/ 09 февраля 2020

Вы не инициализируете идентификатор WireFormatWidget #. Это объявлено, но никогда не инициализировано. Добавьте конструктор в WireFormatWidget и укажите String в качестве идентификатора.

0 голосов
/ 09 февраля 2020

Вам нужно реализовать что-то, что реализует Serializable, или реализовать непосредственно Serializable (я думаю, что это проще).

Вы не указываете много вещей в своем событии интерфейса, но, вероятно, унаследуете от Serializable, по крайней мере, если вы собираетесь реализовать стандартную сериализацию java.

Если Event реализует Serializable, так что все в порядке, в противном случае, если вы используете другой метод сериализации, вам нужно указать больше об этом.

Предполагая, что вы Для реализации Serializable вам нужно создать ByteBuffer и вызвать writeObject. Чтобы создать поток, вы можете проверить, например, Java Сериализуемый объект в массив байтов , поэтому объедините все:

ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream stream = new ObjectOutputStream(bos);   
stream.writeObject(yourinstancetoserialize);
out.flush();
byte[] yourBytes = bos.toByteArray();
...

Возможно, вам потребуется напрямую реализовать writeObject. В этом случае вы используете методы ObjectOutputStream для сериализации свойств, отметьте их, например, в https://docs.oracle.com/javase/7/docs/api/java/io/ObjectOutputStream.html.

private void writeObject(java.io.ObjectOutputStream stream) throws IOException {
  stream.writeInt(this.type);
  stream.writeLong(this.timestamp);
  stream.writeBytes(this.identifier); or stream.writeChars(this.identifier);
  stream.writeInt(this.tracker);
  ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...