Использование буферов протокола для двоичного ведения журнала - PullRequest
7 голосов
/ 10 марта 2010

Мы думаем об использовании буферов протокола для двоичного ведения журнала, потому что:

  • Так или иначе мы кодируем наши объекты
  • Это относительно компактный, быстрый для чтения / записи и т. Д.

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

Первая проблема, с которой мы столкнулись, это то, что мы делаем это (в тесте:

        FileInputStream fileIn = new FileInputStream(logFile);
        CodedInputStream in = CodedInputStream.newInstance(fileIn);
        while(!in.isAtEnd()) {
            DataLogEntry entry = DataLogEntry.parseFrom(in);
            // ... do stuff
        }

В результате только 1 DataLogEntry читается из потока. Без isAtEnd он никогда не останавливается.

Мысли

Редактировать: я переключился на использование entry.writeDelimitedTo и BidLogEntry.parseDelimitedFrom, и это, похоже, работает ...

Ответы [ 2 ]

4 голосов
/ 10 апреля 2011

Начиная с 2.4.0a, по крайней мере, это легко. Напишите ваше сообщение с помощью writeDelimitedTo. Нет необходимости использовать закодированные потоки напрямую.

4 голосов
/ 11 марта 2010

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

public class DataLog {

    public void write(final DataOutputStream out, final DataLogEntry entry) throws IOException {
        out.writeInt(entry.getSerializedSize());
        CodedOutputStream codedOut = CodedOutputStream.newInstance(out);
        entry.writeTo(codedOut);
        codedOut.flush();
    }

    public void read(final DataInputStream in) throws IOException {
        byte[] buffer = new byte[4096];
        while (true) {
            try {
                int size = in.readInt();
                CodedInputStream codedIn;
                if (size <= buffer.length) {
                    in.read(buffer, 0, size);
                    codedIn = CodedInputStream.newInstance(buffer, 0, size);
                } else {
                    byte[] tmp = new byte[size];
                    in.read(tmp);
                    codedIn = CodedInputStream.newInstance(tmp);
                }
                DataLogEntry.parseFrom(codedIn);
                // ... do stuff
            }
            catch (final EOFException e) {
                break;
            }
        }
    }
}

Примечание: я использовал исключение EOFException, чтобы найти конец файла, вы можете использовать разделитель или отслеживать количество прочитанных байтов вручную.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...