C'è qualche pericolo nella scrittura di byte grezzi in un file? [chiuso]

12

Sto lavorando a un problema in Programming Pearls, in particolare l'implementazione di un programma che ordina un file contenente, al massimo, 10.000.000 di interi (Colonna 1, Problema 3). Poiché il libro non specifica come devono essere memorizzati i dati nel file, sto considerando di memorizzare gli interi come byte non elaborati (ci sono altri vincoli che rendono i byte grezzi una buona opzione). Non ho mai lavorato a questo livello basso prima, quindi voglio sapere se c'è qualcosa di pericoloso che dovrei fare attenzione. Devo preoccuparmi di usare accidentalmente una sorta di sequenza di fine file quando sto scrivendo byte grezzi in un file, ad esempio?

Modifica:

Ora mi rendo conto di quanto fosse ampia la mia domanda. Intendevo davvero problemi di tipo più catastrofico, come sovrascrivere accidentalmente altri file sul disco. Scusa se non ero più chiaro in origine.

    
posta Drake Sobania 27.08.2014 - 19:41
fonte

4 risposte

11

L'unico pericolo in cui ti imbatterai è il piccolo o il grande endianess (se il byte più o meno significativo è scritto per primo). Tuttavia se rimani nello stesso ambiente non ci saranno problemi. oltre alla garanzia generale di scrittura / analisi di andata e ritorno.

Il file system è progettato per gestire qualsiasi sequenza di byte.

    
risposta data 27.08.2014 - 19:49
fonte
27

No, in effetti questo è il numero di formati di file funzionanti. Esempi comuni di file binari come questo includono immagini e file musicali / audio.

Per mantenere l'integrità del file e i dati letti da esso, assicurati di seguire queste linee guida:

  • Apri sempre il file (leggendo o scrivendo) usando la stessa modalità: testo o binario. La differenza principale è che la modalità testo si preoccupa delle nuove righe e potrebbe "eliminare" i caratteri di nuova riga durante la lettura di un file (a seconda della libreria specifica utilizzata). La modalità testo può anche eseguire traduzioni Unicode che probabilmente soffocheranno su dati non Unicode.
  • Durante la lettura di dati non stringa, assicurarsi di leggere utilizzando lo stesso tipo di dati durante la scrittura. Ad esempio, se i primi quattro byte del file sono un numero intero descrittivo, assicurarsi di leggere e scrivere utilizzando un metodo che accetta / fornisce un numero intero per garantire che venga trattato in modo coerente. Lo stesso tipo di dati può avere dimensioni diverse su macchine diverse e il mixaggio dei tipi di dati sulla stessa macchina può anche cambiare il significato dei dati (ad esempio, l'interpretazione di un bit nel mezzo di un intero più lungo come un bit di segno).
  • Endianness: se la libreria che stai utilizzando non la gestisce in modo coerente, potrebbe essere necessario gestirla autonomamente. Ad esempio, Java utilizza sempre l'ordine dei byte di rete (big endian) per i tipi a più byte. C e C ++ usano tutto ciò che l'implementatore della libreria ha deciso, tipicamente lo stesso del processore (little endian su Intel, big endian su molti altri). Se questo è un esercizio veloce su un sistema, non è così importante, ma è comunque una buona abitudine prestare attenzione a questo e, se necessario, codificarlo.

I dettagli specifici variano a seconda del framework, della piattaforma e della lingua, ma questo dovrebbe coprire i "trucchi" di base con I / O di file.

    
risposta data 27.08.2014 - 19:56
fonte
9

Oltre a tutti i trucchi già menzionati, se stai creando un nuovo formato di file binario invece di leggere e scrivere dati in un formato esistente, è assolutamente vitale includere un header del file : un blocco di dati all'inizio del file che identifica in modo univoco il formato del file e registra eventuali metadati che potrebbero essere richiesti.

Le buone intestazioni di file includono almeno tre cose:

  • Un " numero magico ", di almeno quattro byte. Il numero magico DEVE rfc2119 essere i primi N byte nel file, NON DEVE mai sono stati utilizzati per qualsiasi altro formato di file che è possibile scavare e DEVE contenere almeno un byte che non sia un carattere ASCII stampabile. Consulta la specifica PNG per come progettare un numero magico approfondito . Consulta il codice sorgente del comando file(1) per un database di numeri magici esistenti che è così completo come è probabile che tu possa trovare .

    Il punto di un numero magico è di etichettare univocamente il file, in-band, con il suo formato. Se non includi un numero magico, o non è la prima cosa nel file, corri il rischio che i programmi identificano erroneamente il tuo file come un altro tipo di file, che porta alla perdita di dati, rilevamento di fughe di virus e altre catastrofi di questo tipo.

  • Un'indicazione della versione del formato del file. Anche se pensi che non dovrai mai modificare drasticamente il tuo formato di file, crea i prossimi due byte dopo che il numero magico è 00 00 e documenta che questo è un numero di versione a 16 bit in un certo endianness definito (a seconda di quale ti piace , ma sceglierne uno e seguitelo su tutto il file ) e verrà incrementato se il significato dei dati successivi cambia radicalmente. Il tuo sé futuro ti ringrazierà

    (Le specifiche PNG qui seguono un percorso diverso, specificando che i formati del blocco sono congelati e che tutte le future modifiche al formato assumeranno la forma di nuovi tipi di blocco. Anche questo è valido, ma io raccomando il numero magico semplice + versione approccio numerico per i principianti all'elaborazione di dati binari. Le persone che hanno progettato PNG stavano attingendo a decenni di esperienza collettiva con i formati di immagini.)

  • Un tipo di meccanismo per incorporare metadati arbitrari nel file. Questo può essere tanto semplice quanto avere i next due byte come offset a 16 bit dalla fine dell'intestazione all'inizio dei dati effettivi, con tutto il resto da interpretare come tasto UTF-8 -value pairs a la RFC 822 (cioè " Tag: value\n " - se segui questa strada ti consiglio not di consentire la piegatura di linee lunghe). Ancora una volta, PNG è considerevolmente più intelligente.

risposta data 28.08.2014 - 02:42
fonte
2

Diverse architetture hanno rappresentazioni differenti per interi. Il principale rischio qui è il salvataggio della rappresentazione in byte di un intero nella macchina A e quindi il tentativo di leggere quello indietro e interpretare il contenuto come numeri interi nella macchina B. Se le macchine A e B hanno dimensioni diverse per interi e / o diversi endianness , molto probabilmente causerai un comportamento non definito (ad esempio in C) o un'eccezione.

Poiché questo è solo un esempio di programmazione e non un programma "reale", non è davvero un problema. Se questo fosse un vero programma, il rollare il proprio formato binario specifico dell'applicazione non è solitamente una buona idea; ci sono soluzioni migliori, come SQLite o formati di serializzazione basati su stringhe come JSON, YAML, XML, ecc. Per i singoli valori è sufficiente trasformarlo in una stringa; per gli elenchi semplici è possibile salvare una stringa per riga e dividere semplicemente l'input su newline quando lo si legge di nuovo.

    
risposta data 27.08.2014 - 19:50
fonte

Leggi altre domande sui tag