2010-05-26 11 views
5

Utilizzando C#, ho bisogno di leggere un file binario compresso creato utilizzando FORTRAN. Il file viene salvato in un formato "non formattato sequenziale" come descritto qui (circa a metà strada in basso nella pagina nella sezione "non formattato Sequential Files"):analizza il contenuto dalla struttura in un file binario

http://www.tacc.utexas.edu/services/userguides/intel8/fc/f_ug1/pggfmsp.htm

Come si può vedere dalla URL, il il file è organizzato in "blocchi" di 130 byte o meno e include 2 byte di lunghezza (inseriti dal compilatore FORTRAN) che circondano ogni blocco.

Quindi, ho bisogno di trovare un modo efficiente per analizzare il reale carico utile del file lontano dalla formattazione del compilatore.

Dopo aver estratto il carico utile effettivo dal file, ho quindi bisogno di analizzarlo nei suoi vari tipi di dati. Questo sarà il prossimo esercizio.

I miei primi pensieri sono di borseggiare l'intero file in un array di byte usando File.ReadAllBytes. Quindi, basta scorrere i byte, saltare la formattazione e trasferire i dati effettivi in ​​un secondo array di byte.

Alla fine, quella matrice di secondo byte dovrebbe contenere il contenuto del file effettivo meno tutta la formattazione, che avrei quindi bisogno di tornare indietro per ottenere ciò di cui ho bisogno.

Dato che sono abbastanza nuovo per C#, ho pensato che ci sarebbe stato un modo migliore e più accettato di affrontarlo.

Inoltre, nel caso in cui è utile, questi file potrebbero essere abbastanza grande (diciamo 30 MB), se la maggior parte sarà molto più piccola ...

risposta

1

Un modo per leggere i file di questo tipo è record per record (ad esempio, leggere i byte di lunghezza e quindi il blocco di dati, creando un elenco di record, che sono solo array di byte). La raccolta di record viene quindi passata ad ulteriori routine di analisi.

Tuttavia, se si è su 4.0, c'è un new class per la mappatura dei file che sarebbe più efficiente ma funziona allo stesso modo di ReadAllBytes.

Se si utilizza ReadAllBytes o MemoryMappedFile è piacevole creare un "indice" in memoria nel file binario di grandi dimensioni analizzando prima tutte le lunghezze del record. Questo è particolarmente utile se hai bisogno di determinati record.

+0

Grazie. Sulla base dei tuoi commenti, ho scritto del codice che carica il mio file in un array di byte e produce un secondo array di byte pulito (privo di indicatori di lunghezza).Ora sto tentando di analizzarlo in vari valori scalari usando BitConverter, anche se mi sembra un po 'brutto in quanto ho bisogno di mantenere il mio puntatore nell'array mentre lo converto. Supponendo che io continui con l'array di byte, c'è un modo migliore per ottenere vari scalari da esso? Oh, e non sto usando 4.0 ... –

+0

È possibile avvolgere l'array di byte in un 'MemoryStream' e usare un' BinaryReader'. 'BinaryReader' ricorda la propria posizione quindi non è necessario. –

0

Invece di scorrere i byte, dare un'occhiata a System.IO.BinaryReader. Apri il file come FileStream, racchiudilo in un BinaryReader e puoi leggere direttamente i tipi primitivi, con il puntatore dello stream che tiene traccia del tuo offset nel blob. Potrebbe essere necessario tenere conto di endianness e tipi personalizzati, magari creando i propri metodi di estensione per BinaryReader in base al suo metodo per la lettura di singoli byte.

Se i dati sono necessari in un array di byte, è comunque possibile utilizzare BinaryReader se si esegue il wrapping dell'array in un MemoryStream.

Con file così grandi, eviterei lo File.ReadAllBytes. FileStream dovrebbe buffer per te, e il suggerimento di Stephen per l'utilizzo di file mappati in memoria suona come un'alternativa più sofisticata (possibilmente più efficiente), specialmente se devi fare un secondo passaggio per la formattazione.

+0

Grazie. Il problema che vedo dopo averlo seguito direttamente con BinaryReader è che i dati sono inquinati da indicatori di lunghezza (come indicato nell'URL del post originale). Quindi, non posso semplicemente iniziare a leggere le mie primitive come i marcatori di lunghezza faranno scattare il puntatore del flusso. Per questo motivo, sembrerebbe più pulito scrubare prima i dati dei marcatori di lunghezza e quindi elaborarli in una seconda fase. Tuttavia, ciò significa ingoiare l'intera cosa nella memoria prima. Vedete un modo semplice per evitare gli indicatori di lunghezza e utilizzare BinaryReader in un unico passaggio? –

+0

Ah, capisco. Bene, ora che hai il codice per produrre dati non inquinati, invece di usare BitConverter, puoi costruire un MemoryStream da ogni array, che si prende cura del problema del puntatore dell'array (MemoryStream ha un costruttore per il wrapping di array esistenti, piuttosto che allocare il proprio) . Quindi avvolgere il MemoryStream in un BinaryReader. – shambulator

+0

Ah, ora sembra promettente (MemoryStream racchiuso in un BinaryReader). Fammi vedere cosa riesco a capire. Grazie. –

Problemi correlati