Protobuf streaming (la serializzazione pigra) API

Abbiamo un'applicazione Android che utilizza Protocol Buffers per memorizzare i dati delle applicazioni. Il formato dei dati (approssimativamente) è una singola protobuf ("contenitore") che contiene un elenco di protobufs ("oggetti") come field ripetuto:

message Container { repeated Item item = 1; } 

Quando vogliamo salvare una modifica a un elemento, dobbiamo ricreare il contenitore di protobuf, aggiungere tutti gli elementi ad esso, poi serializzarlo e scrivere in un file.

  • Convertitore personalizzato per Retrofit 2
  • Come get l'ID del thread Android?
  • Imansible trovare com.google.android.gms: play-services: 8.4.0
  • Come aggiungere ToolBar in PreferenceActivity?
  • Lanciare uno script come root tramite ADB
  • Come controllare un dispositivo Android è schermo HDPI o schermo MDPI?
  • Il problema di questo approccio è che triplica la memory utilizzata durante il salvataggio perché i dati vanno prima da copiare dalla class model al constructor di protocollo e poi ad un arrays di byte quando la protobuf viene serializzata, prima di scrivere su un file stream.

    Quello che vorremmo è un modo per creare il nostro contenitore di protobuf e serializzarlo pigmentosamente in un stream, quindi aggiungere semplicemente each elemento protobuf (creato dai nostri dati model) al contenitore che la serializza e lo scriverà nel stream, piuttosto che mantenere tutti i elementi in memory finché non abbiamo creato l'integer contenitore in memory.

    C'è un modo per build una protobuf e serializzarlo pigramente a un stream?

    Se non esiste un modo per farlo ufficialmente, ci sono delle biblioteche che possono aiutare? Qualcuno ha suggerimenti o idee come risolvere questo in altri modi? Formati o tecnologie di dati alternativi (ad es. JSON o XML che contengono protobufs) che lo rendano ansible?

  • Possiamo submit dati da un dispositivo android a un altro dispositivo Android direttamente (p2p) senza server al centro?
  • come creare una serie di stringhe di Json in android
  • Android - GoogleSignInResult sempre fallito
  • Gli elementi presenti su ListView in Widget non visualizzano
  • Gestore di clic del button Android GridView
  • Modo autorevole per superare onMeasure ()?
  • 3 Solutions collect form web for “Protobuf streaming (la serializzazione pigra) API”

    Per la serializzazione:

    il protobuf è un formato appendibile, con l'unione di singoli elementi e l' aggiunta di elementi ripetuti

    Pertanto, per scrivere una sequenza come un stream pigro, tutto quello che devi fare è ripetutamente scrivere la stessa struttura con solo una voce nell'elenco: la serializzazione di una sequenza di 200 x "Container con 1 elemento" è 100% identica alla serializzazione di 1 x "Container con 200 articoli".

    Così: basta farlo!


    Per la deserializzazione:

    Questo è tecnicamente molto facile da leggere come un stream – tutto ciò, tuttavia, scende a quale libreria si sta utilizzando. Ad esempio, la esporrò in protobuf-net (implementazione .NET / C #) come Serializer.DeserializeItems<T> , che legge (completamente pigra / streaming) una sequenza di messaggi di tipo T , in base all'assunto che siano in il module che descrivi nella domanda (quindi Serializer.DeserializeItems<Item> sarebbe il modo di streaming che sostituisce Serializer.Deserialize<Container> – l'object più esterno tipo non esiste in protobuf)

    Se questo non è disponibile, ma è ansible accedere a un API di lettura raw, è necessario:

    • leggere un varint per l'intestazione – questo sarà il valore 10 (0x0A), cioè "(1 << 3) | 2" rispettivamente per il numero di field (1) e il tipo di filo (2) – quindi questo potrebbe anche essere formulato: "leggere un singolo byte dal stream e verificare che il valore sia di 10"
    • leggere una varint per la lunghezza del seguente elemento
    • adesso:
      • se l'API del lettore consente di limitare il numero massimo di byte da elaborare, utilizzare questa lunghezza per specificare la lunghezza che segue
      • o avvolgere l'API di stream con un stream di lunghezza limitato, limitato a tale lunghezza
      • o semplicemente leggere manualmente molti byte e build un stream in memory dal carico utile
    • risciacquare, ripetere

    Non vi è nulla di simile. Un protobuf è una struttura imballata. Per farlo in modo efficace avrebbe bisogno di tutti i dati. Dovrai aggiungere il "protocollo di streaming". Forse submit un messaggio prototipo a each elemento N.

    Nella versione normale di java dei buffer di protocollo ci sono file delimitati in cui si scrivono Protocol-Buffers uno alla volta. Non sono sicuro se è nella versione Android

      aLocation.writeDelimitedTo(out); 

    Come Marc lo ha indicato facilmente implementato; basta scrivere una lunghezza seguita dai byte serializzati. Nella versione normale (non android) di java di prortocol-buffer si può anche fare (si deve serializzare un arrays di byte o qualcosa di simile)

     private CodedOutputStream codedStream = null; public void write(byte[] bytes) throws IOException { if (bytes != ConstClass.EMPTY_BYTE_ARRAY) { codedStream.writeRawVarint32(bytes.length); codedStream.writeRawBytes(bytes); codedStream.flush(); } } 

    e

      private CodedInputStream coded; public byte[] read() throws IOException { if (coded == null) { throw new IOException("Reader has not been opened !!!"); } if (coded.isAtEnd()) { return null; } return coded.readBytes().toByteArray(); 

    Qualcosa può essere ansible in altre versioni di Protocol-Buffers

    L'Android è un fan Android di Google, tutto su telefoni Android, Android Wear, Android Dev e applicazioni Android Games e così via.