2010-03-10 19 views
7

Stiamo pensando di utilizzare buffer protocollo per la registrazione binaria perché:Uso buffer di protocollo per la registrazione binaria

  • E 'come stiamo codifica i nostri oggetti comunque
  • è relativamente compatto, veloce in lettura/scrittura ecc

detto questo, non è ovvio come dovremmo andare su di esso, perché le API tendono a concentrarsi sulla creazione di oggetti interi, in modo da avvolgere un elenco di DataLogEntry come un campo ripetuto in un DataLogFile sarebbe quello che si fare in termini di messaggistica, ma quello che vogliamo veramente è solo quello di essere in grado di wr ite e poi leggere un'intera DataLogEntry, aggiungendola alla fine di un file.

Il primo problema che abbiamo colpito così facendo è che facendo questo (in un test:..

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

Solo risultati in 1 DataLogEntry vengono letti dal flusso Senza l'isAtEnd, non si ferma mai

Pensieri

Edit:? ho passato a utilizzare entry.writeDelimitedTo e BidLogEntry.parseDelimitedFrom e che sembra funzionare ...

+0

Quindi, cosa hai finito? Qualche commento 2 anni dopo? – bstempi

risposta

4

Dal mio comprensione dei buffer di protocollo è does not support più messaggi in un singolo flusso. Quindi probabilmente dovrai tracciare i confini dei messaggi da solo. puoi farlo memorizzando la dimensione del messaggio prima di ogni messaggio nel registro.

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; 
      } 
     } 
    } 
} 

NB: ho usato un EOFException per trovare alla fine del file, si potrebbe desiderare di utilizzare un delimitatore o tenere traccia del numero di byte di leggere manualmente.

+0

Fantastico, grazie. Proprio quello che dovevo sapere. Mi chiedo quanto sia fragile ... Immagino che le cose brutte accadano se ho perso l'inizio del file ... –

+0

Hmmm ... ricevendo questo errore quando cercavo di leggere: Il messaggio di protocollo conteneva un tag non valido (zero). –

+0

CodedOutputStream deve essere svuotato. –

4

A partire da 2.4.0a, almeno, questo è facile. Scrivi il tuo messaggio con writeDelimitedTo. Non è necessario utilizzare direttamente i flussi codificati.

Problemi correlati