Quali interfacce C ++ IO per una sorgente di dati complessa, ad esempio un convertitore

4

La mia domanda:

Quando hai un convertitore complesso come, che prende blocchi o set di risultati di grandi dimensioni da un database, alla fine lo converte in un file riga / risorsa, nel caso uno lo disegni come std::basic_streambuf o è un std::basic_istream o qualcosa di diverso, usando C ++ ?!

Per meglio descriverlo guarda il diagramma qui sotto o usa questo flusso di dati di testo:

A(ODB) -[maybe many rows]-> COSTLY CONVERSION  -[many text lines]->  ????  --> std::istream
                                                                     ????  --> std::ofstream
                                                                     ????  --> std::ostream

Nota: il volume dei dati potrebbe essere ampio, da MB fino a GB, quindi i dati potrebbero essere convertiti in blocchi e pigri dal database, il che porterà a un blocco di righe di testo. Il mio approccio assunto al momento per ???? era std::basic_streambuf

La mia ipotesi:

AFAIK il modo previsto di inserire dati da una fonte std::istream in un altro std::ostream sink, come std::ofstream è di usare solo <<operator con l'argomento% std::streambuf , come

sink << source.rdbuf();

Sfondo

Sto progettando un modulo convertitore C ++, che prende dati personalizzati (cioè dati di misura), in questo esempio da un database mddb tramite la libreria C ++ odb , lo converte in un altro formato, chiamato df qui, e ora arriva la parte importante: rende disponibili i dati convertiti per almeno un std::istream e anche un std::fstream . Questo perché, il std::istream può essere utilizzato per un download HTTP tramite l'interfaccia Wt Wt::WStreamRessource e ovviamente il flusso del file, per memorizzare semplicemente i dati come file.

    
posta Superlokkus 04.02.2016 - 18:36
fonte

1 risposta

1

Innanzitutto, un std::basic_streambuf è fondamentalmente il blocco predefinito di std::XYZstream . L'utilizzo dell'uno o dell'altro non consente di scegliere tra due implementazioni, ma è una scelta tra un blocco di base e un'interfaccia di flusso più avanzata che le persone si aspettano. Utilizza uno stream.

In base ai tuoi commenti, sembra che tu possa rimanere bloccato dall'idea di buffering .

Prova a pensare a questo come qualcosa di simile alla lettura di righe da un file, eccetto che stai leggendo i record da un database. Invece di leggere un file riga per riga, stai tirando i dati da un record della tabella per record:

idbstream in(<DB connection info here>);
ostream out(...);
while (in) {
  db_record r;
  in >> r;
  out << r;
}

Nella tua estrazione idbstream::operator>>(db_record&) gestisci la tua logica di query, inserendo un buffer di input sufficiente per essere in grado di costruire un oggetto record DB, qualunque cosa tu abbia bisogno. Si ritorna solo quando si dispone di un record DB completo e si è aggiornato tale oggetto. Puoi anche rinunciare completamente allo zucchero sintattico di operator>> e fare una costruzione di spostamento e tornare all'interno del tuo stream:

db_record idbstream::readRecord() { ... }

out << in.readRecord();

Per efficienza, db_record dovrebbe avere un costruttore di movimento e dovrebbe essere creato nello stesso momento in cui viene restituito.

Infine, i dettagli di in che modo lo stream DB esegue la conversione vengono deliberatamente lasciati non specificati. È possibile utilizzare un adattatore o una logica più complessa per selezionare il tipo di oggetto e convertire più tipi di record.

Si noti inoltre che il flusso di output è proprio questo, un flusso di output. Non faccio supposizioni su cosa ci sia dall'altra parte di quel flusso. Come alluderai ai tuoi commenti potrebbe essere un file, standard out, una connessione HTTP, qualunque cosa ti serva. La classe record DB stessa gestirà la sua serializzazione in modo indipendente dall'implementazione (l'unica cosa che conta davvero è il testo binario v.)

    
risposta data 06.02.2016 - 16:39
fonte

Leggi altre domande sui tag