7

次の理由により、バイナリログにプロトコル バッファを使用することを考えています。

  • とにかくオブジェクトをエンコードする方法です
  • 比較的コンパクトで、読み取り/書き込みなどが高速です。

とはいえ、API はオブジェクト全体の作成に重点を置く傾向があるため、どのように対処すべきかは明らかではありません。そのため、DataLogEntry のリストを DataLogFile の繰り返しフィールドとしてラップすることは、メッセージング用語で行うことですが、私たちが本当に望んでいるのは、DataLogEntry 全体を書き込んでから読み込んで、ファイルの末尾に追加できるようにすることです。

それを行うことで最初に遭遇した問題は、これを行うことです(テストでは:

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

ストリームから読み取られる DataLogEntry は 1 つだけになります。isAtEnd がなければ、停止することはありません。

考え?

編集: entry.writeDelimitedTo と BidLogEntry.parseDelimitedFrom の使用に切り替えましたが、うまくいくようです...

4

2 に答える 2

4

プロトコル バッファに関する私の理解では、単一のストリームで複数のメッセージをサポートしていません。そのため、おそらくメッセージの境界を自分で追跡する必要があります。これを行うには、ログ内の各メッセージの前にメッセージのサイズを保存します。

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 を使用しました。区切り文字を使用するか、手動で読み取ったバイト数を追跡​​することをお勧めします。

于 2010-03-10T22:02:26.870 に答える
4

少なくとも 2.4.0a では、これは簡単です。writeDelimitedTo でメッセージを書きます。コード化されたストリームを直接使用する必要はありません。

于 2011-04-10T11:48:32.640 に答える