2015-08-21 15 views
5

Per favore perdonami se c'è una risposta lampante a questa domanda; Non l'ho trovato perché non sono completamente sicuro di quello che sto cercando. Potrebbe essere questo duplica una domanda che non ho trovato; scusa.C - Memorizzazione di un grande gruppo di file come risorsa singola

Ho un eseguibile C che utilizza testo, audio, video, icone e una varietà di diversi tipi di file. Questi file sono memorizzati localmente; la struttura delle cartelle è ampia e profonda e dovrebbe essere installata insieme all'applicazione per funzionare correttamente (non che io prevedo che sia distribuita, sto cercando di impacchettare il mio lavoro per comodità).

A mio parere sarebbe più conveniente se la libreria di file fosse archiviata in un singolo file che rimanesse accessibile all'applicazione ad esempio a fianco di /usr/bin/APPLICATION o nella posizione più appropriata; accesso all'eseguibile quando richiesto.

Ho cercato per domande simili e trovato suggerimenti che indicavano due possibili opzioni Resource Files che sembrano essere nativo di Windows e Including files at compile. La prima domanda porta a una risposta simile alla seconda e non risponde alla domanda relativa all'esistenza di file di risorse per gli eseguibili di Linux. Questo (come il secondo) esamina l'inserimento del file di dati nel processo di compilazione. Non è così utile come se volessi aggiornare le mie risorse. Sono costretto a ricompilare l'intera applicazione (il supporto è aggiunto dinamicamente).

DOMANDA: C'è un modo per archiviare una varietà di tipi di file in un singolo file accessibile a un eseguibile in linux e, in caso affermativo, come lo implementeresti?

Il mio pensiero su questo inizialmente era quello di creare un file .zip o .gz che potrebbero anche offrire compressione come un ulteriore bonus, ma non ho idea di come (o se è ancora possibile) per accedere ai dati all'interno di tale file sul volare. Sono ugualmente incerto se esiste un tipo di file o una libreria specifici che offre una soluzione più adatta. Inoltre, non so praticamente nulla dei file .dat che potrebbero essere utilizzati in questo contesto su un sistema Linux?

+2

'file .dat' può significare qualsiasi cosa; Non conosco un formato di file '.dat' standard. '.zip' sembra una buona scelta (java lo usa per i vasi); guarda in 'libzip'. –

+0

Apparentemente Zip può facilmente estrarre solo il file che si desidera, ma non tar/gz. Vedere http://gamedev.stackexchange.com/questions/37648/how-can-you-put-all-images-from-a-game-to-1-file –

+0

è possibile memorizzare tutti i nomi dei file in un unico file di testo, (con sezioni per ogni tipo di file, o forse un file di testo per ogni tipo di file) che è/sono analizzato dal programma. Quindi non è necessario continuare a ricompilare la fonte, dove probabilmente si codificano i nomi dei file delle risorse. "File di risorse" è un termine solitamente associato alla compilazione, come la definizione di icone, cursori e finestre di dialogo, piuttosto che i dati da elaborare. –

risposta

3

Non capisco perché si utilizzi un singolo file. Considerando l'aggiunta di complessità (e maggiore probabilità di insinuarsi di bug) dell'estrazione di file e dei relativi overhead, non vedo come sarebbe "più conveniente".

Ho un eseguibile C che utilizza testo, audio, video, icone e una varietà di diversi tipi di file.

Così fanno molte altre applicazioni Linux. L'approccio normale, quando si utilizza la gestione dei pacchetti, consiste nel mettere i dati indipendenti dall'architettura (icone, audio, video e così via) per l'applicazione /usr/bin/YOURAPP in /usr/share/YOURAPP/ e i dati dipendenti dall'architettura (come i binari di supporto) in /usr/lib/YOURAPP. È estremamente comune che gli ultimi due siano alberi di directory completi, a volte piuttosto profondi e ampi.

Per le cose compilato a livello locale, è comune a mettere questi in /usr/local/bin/YOURAPP, /usr/local/share/YOURAPP/, e /usr/local/share/YOURAPP/ invece, proprio per evitare di confondere il gestore di pacchetti. (Se si controllano gli script ./configure o si legge Makefile s, questo è lo scopo principale della variabile PREFIX che supportano.)

E 'anche comune per il /usr/bin/YOURAPP di essere un semplice script di shell, delle variabili di ambiente, o di controllo per sostituzioni specifiche dell'utente (da $HOME/.YOURAPP/), finendo con exec /usr/lib/YOURAPP/YOURAPP.bin [parameters...], che sostituisce la shell con l'eseguibile binario attuale senza lasciando la shell in memoria.

Ad esempio, /usr/share/octave/ sulla mia macchina contiene un totale di 138 directory (in una gerarchia di fino a 7 directory in profondità) e 1463 file; circa dieci megabyte di "roba" tutto sommato. LibreOffice, Eagle, Fritzing e KiCAD occupano centinaia di megabyte ciascuno, quindi Octave non è nemmeno un esempio estremo.

+0

Sono d'accordo, e vedere il [filesystem] (https://wiki.linuxfoundation.org/en/FHS) [Gerarchia] (http://www.pathname.com/fhs/) [Standard] (https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard) per i dettagli su dove mettere cosa. –

+0

Penso che questo risponda alla domanda dal punto di vista della necessità di creare un singolo file di risorse per un'applicazione. In realtà non mi sento così male avere una considerevole collezione di risorse. – Chortle

+0

Penso che ci possano essere contesti in cui un individuo non può volere che le sue risorse siano disponibili come un software o un gioco con licenza. Le risorse potrebbero richiedere molto tempo per essere generate e l'individuo potrebbe non volere che vengano distribuite separatamente. Tuttavia sono d'accordo con te in questo contesto, quindi grazie. – Chortle

1

esistono varie alternative (TODO: aggiungere più;)):

potete leggere alcune specifiche di formato file di archiviazione, scrivendo codice per leggere/scrivere a quei software di archiviazione, e sprecare il vostro tempo facendo così.

si può inventare un formato di file sporca, semplice, ad esempio ("DSA" sta per "Archiver sporca e semplice"):

#include <stdint.h> 

// Located at the beginning of the file  
struct DSAHeader { 
    char   magic[3];   // Shall be (char[]) { 'D', 'S', 'A' } 
    unsigned char endianness;   // The rest of the file is translated according to this field. 0 means little-endian, 1 means big-endian. 
    unsigned char checksum[16];   // MD5 sum of the whole file. (when calculating checksums, this field is psuedo-filled with zeros). 
    uint32_t  fileCount; 
    uint32_t  stringTableOffset; // A table containing the files' names. 
}; 

// A dsaHeader.fileCount-sized array of DSAInodeHeader follows the DSAHeader. 
struct DSANodeHeader { 
    unsigned char type;    // 0 means directory, 1 means regular file. 
    uint32_t  parentOffset;  // Pointer to the parent directory, or zero if the node is in the root. 
    uint32_t  offset;   // The node's type-dependent header starts here. 
    uint32_t  nodeSize;   // In bytes for files, and in number of entries for directories. 
    uint32_t  dataOffset;  // The file's data starts at this offset for files, and a pointer to the first DSADirectoryEntryHeader for directories. 
    uint32_t  filenameOffset; // Relative to the string table. 
}; 

typedef uint32_t DSADirectoryEntryHeader; // Offset to the entry's DSANodeHeader 

La "tabella di stringhe" è una sequenza contigua di terminazione null stringhe di caratteri.

Questo formato è molto semplice (e portatile;)). E, come bonus, se vuoi (de) compressione, puoi usare qualcosa come Zip, BZ2 o XZ per (de) comprimere il tuo file (quei programmi/formati sono indipendenti dall'archiver, cioè non dipendenti da tar, come comunemente creduto).

Come ultimo ultimo (o primo?) Ricorso, è possibile utilizzare una libreria/API esistente per la manipolazione di archiviatori e formati di file compressi.

Modifica: Aggiunto il supporto per le directory :).

+0

Mi piace molto l'idea di un formato di file anche se questo è probabilmente un po 'al di fuori del mio skillset, avresti bisogno di usare una funzione per serializzare i dati su un 'unit32_t'? allora deseralizzare o sono completamente fuori di qui? – Chortle

+0

Hai ragione. Se lo desideri, puoi sbarazzarti del campo 'endianness' e fare semplici letture e scritture.Ma, se vuoi andare davvero portabile, lascerai quel campo lì e convertiti tra little endian e big endian se necessario. Per sporcizia e scopi rapidi, puoi anche rimuovere il checksum per ora, se lo desideri. – 3442

+0

Sembra davvero stupido, ma cos'è endian? Sarei molto interessato a leggere su formati di file personalizzati conosci qualche buona risorsa? Potrei google ma c'è un tale mix di qualità che vale sempre la pena di chiedere prima. – Chortle

0

Diciamo che avere:

top-level-folder/ 
    | 
    - your-linux-executable 
    - icon-files-folder/ 
    - image-files-folder/ 
    - other-folders/ 
    - other-files 

fare questo (all'interno top-level-folder)

tar zcvf my-package.tgz top-level-folder 

ad espandersi, fare questo:

tar zxvf my-package.tgz 
1

Ho un C eseguibile che usa il testo , audio, video, icone e una varietà di diversi tipi di file. Questi file sono memorizzati localmente; la struttura delle cartelle è ampia e profonda e dovrebbe essere installata insieme all'applicazione per funzionare correttamente.

Considerando la complessità dei tipi di file associati differrent alongwith struttura di cartelle grande e profonda e richiesto installato con l'applicazione. Aggiungere un singolo file di risorse sarebbe difficile o direbbe vicino a non poter rintracciare le modifiche nel caso in cui si desideri modificare le risorse in modo dinamico. Certamente, l'aggiunta di risorse al file eseguibile non è un'opzione in quanto aumenterà la dimensione del file eseguibile e sarà necessaria una frequente ricompilazione in caso di aggiornamento delle risorse.

Dopo aver esaminato tutti gli aspetti del progetto, mi sembra che la soluzione utilizzi il file INI.INI verrebbe memorizzato nella posizione definita e le altre risorse dovrebbero essere private nel file INI. Come con INI è possibile memorizzare facilmente le posizioni di risorse, le chiavi e le dimensioni di hash e controllare facilmente le modifiche o aggiornare le risorse.

Dal momento che si sta utilizzando le versioni già compressi dal tipo di file e quindi generale Zipping algos non funzionerebbe come il tasso sarebbe molto bassa. Quindi raccomandare di usare 7g algos per la compressione. Da vari algo suggerirei di optare per xz zippare come al solito utilizzato da molti progetti opensource per comprimere i binari e ridurre le dimensioni.

Foreach compressione dei file la sua CRC32 o valore di hash dovrebbe anche incluso nel file INI per verificare la validità dei dati trasferiti.