2014-07-21 60 views
1

採取谷歌的教程的例子:如何在一個protobuf文件中寫入多條消息?

message Person { 
    required string name = 1; 
    required int32 id = 2; 
    optional string email = 3; 

    enum PhoneType { 
    MOBILE = 0; 
    HOME = 1; 
    WORK = 2; 
    } 

    message PhoneNumber { 
    required string number = 1; 
    optional PhoneType type = 2 [default = HOME]; 
    } 

    repeated PhoneNumber phone = 4; 
} 

message AddressBook { 
    repeated Person person = 1; 
} 

它使用一個地址簿包裝消息作爲存儲多個個人的消息。如果我序列化或反序列化它,我使用的方法如AddressBook.mergeFrom(FileInputStream)addressBook.build.().writeTo()

但它會明顯溢出,如果我有2000萬人記錄。谷歌也表示,如果我想在一個文件中存儲多條消息而不使用包裝消息,那麼我需要記錄每條消息的長度,這對字符串類型來說是不可能的。

有沒有一種很好的方法來在一個文件中序列化大量的消息? 而我正在使用Java的方式。

回答

2

我沒有試過,但是我希望它的工作:

寫作:

CodedOutputStream output = CodedOutputStream.newInstance(...); 

while (...) { 
    Person person = ...; 
    output.writeMessageNoTag(person); 
} 

閱讀:

CodedInputStream input = CodedInputStream.newInstance(...); 
while (!input.isAtEnd()) { 
    Person.Builder builder = Person.newBuilder(); 
    input.readMessage(builder, null); // Or specify extension registry 
    Person person = builder.build(); 
    // Use person 
} 
0

在Java中,你可以使用writeDelimitedToparseDelimitedFrom用於寫入和讀取相同類型的多個消息的方法。

MessageLite documentation

writeTo(OutputStream),但寫數據之前寫消息作爲varint的大小。這允許在消息之後將更多數據寫入到流中,而無需親自分隔消息數據。使用MessageLite.Builder.mergeDelimitedFrom(InputStream)(或靜態方法YourMessageType.parseDelimitedFrom(InputStream))解析用此方法寫入的消息。

實施例:

// writing 
List<Person> addressBook = ...; // list of person to be stored 
try(FileOutputStream output = new FileOutputStream(path)) { 
    for (Person person: addressBook) { 
    person.writeDelimitedTo(output); 
    } 
} 

// reading 
try (FileInputStream input = new FileInputStream(path)) { 
    while (true) { 
    Person person = Person.parseDelimitedFrom(input); 
    if (person == null) { // parseDelimitedFrom returns null on EOF 
     break; 
    } 

    // use person 
    } 
} 
相關問題