Come creare un archivio ad accesso casuale di file di testo?

1

Ho scritto un'applicazione che verifica le prestazioni degli algoritmi evolutivi. Questa applicazione esegue un run dell'algoritmo che consiste in diverse generazioni . I dati prodotti dalla mia applicazione hanno questo aspetto:

run1.run             // text file containing metadata
run1_data            // folder containing experimental data
   -statistics1      // text file containing some specific statistics
   -statistics2     
   -generation0     
   -generation10     // snapshot of the algorithm at generation10
   -generation20
   ...

Una volta scritti questi dati, non viene mai modificato .

Quando voglio esaminare i dati, la mia applicazione legge il file metadata (.run), apre la directory _data e legge il resto dei dati.

Questo andava bene fino a poco tempo fa. Ora ho centinaia di migliaia di questi file e ho esaurito gli inode sul mio sistema e anche il caricamento dei dati e la copia sono estremamente lenti, anche se ci sono solo pochi gigabyte. I miei dati sembrano essere troppo frammentati, dal momento che i file sono piuttosto piccoli.

La mia applicazione è scritta in C ++ e utilizza la libreria Qt per le operazioni del filesystem. Stavo pensando di usare l'intestazione <system> per emettere un comando tar per archiviare i dati dopo aver scritto e non archiviato prima di leggere, ma ho scoperto che tar deve leggere l'intero archivio per trovare il contenuto. Questo è un problema per me, dato che per risparmiare memoria operativa e tempo a volte carico solo Statistics1 , a volte solo generation10 ...

Stavo pensando di cambiare il formato dei miei dati in modo che ci fosse solo un file , che avrebbe qualcosa come un sommario all'inizio, seguito tutti i file di dati concatenati . Il sommario indicherà inizio e fine di ciascun file concatenato. Tuttavia non sono sicuro che questa sia una buona soluzione dato che la classe std::ifstream che uso per leggere i file non può eseguire salti casuali .

Sono un programmatore principiante e non voglio sprecare molto tempo nello sviluppo di qualcosa che non funziona, quindi chiedo consigli su come risolvere il mio problema.

    
posta Martin Drozdik 24.06.2014 - 18:17
fonte

3 risposte

3

Potresti prendere in considerazione l'utilizzo di una libreria di file indicizzati come gdbm (o altro).

Potresti anche prendere in considerazione l'idea di utilizzare sqlite (è un po 'eccessivo, ma imparare alcuni piccoli SQL è utile!) - o anche usando un vero sistema di database (es. postgresql o mongodb ). Non dimenticare di eseguire il backup e amp; eseguire il dump dei dati nel formato database (ad es. SQL).

Potresti anche essere interessato a formati di serializzazione testuale come JSON (ci sono delle librerie per loro, ad esempio jsoncpp , ed è bello gestire i dati testuali). Puoi inserire dati JSON all'interno di contenitori GDBM o sqlite (vedi questo esempio dei miei ).

BTW, se vuoi mantenere molti file, magari organizzarli nelle directory (ad es. dir01/data0020 ....) potrebbe essere d'aiuto.

Probabilmente vorrai creare un'applicazione di supporto per sfogliare o accedere ai tuoi dati ... Pensa anche al backup dei tuoi dati in formato testuale (non binario)!

Ci sono alcune librerie che gestiscono il formato tar come libtar ma suppongo che non dovresti usarle.

Guarda anche se il tuo campo (algoritmi evolutivi) non ha definito alcune convenzioni o formati. Scrivi il tuo formato (anche per te!).

    
risposta data 24.06.2014 - 18:36
fonte
2

Puoi anche usare un file zip. È come tar, ma l'indice è conservato alla fine del file e viene trovato cercando fino alla fine del file.

Se non comprimi quando crei lo zip, allora è proprio come un tar, ma con la possibilità di cercare qualsiasi file all'interno, e puoi persino mmapare le voci.

È meglio di sqlite perché è facile sfogliare un file zip e molte utilità di file possono trattare un file zip come una cartella. BeyondCompare può anche confrontare due file zip proprio come confrontare due cartelle.

    
risposta data 24.06.2014 - 22:05
fonte
1

Il suggerimento sqlite è buono se ritieni che i tuoi dati siano relazionali. Puoi spremere i dati in sqlite se anche se non è relazionale, tuttavia, un database nosql potrebbe essere una scelta migliore. Ad esempio, Mongodb potrebbe essere una buona scelta o i redis potrebbero essere delle buone scelte.

A proposito, fstream va bene con l'accesso casuale. Vedi seekg .

    
risposta data 24.06.2014 - 21:33
fonte

Leggi altre domande sui tag