Quali pratiche di codifica sono più utili per gestire lo spazio bianco finale nei campi dati in file binari?

3

Abbiamo un'applicazione che consiste in file binari (contenenti un mix di testo e informazioni numeriche) e programmi scritti in varie lingue che creano, modificano e leggono questi file binari. Poiché i campi di testo sono memorizzati in un file binario, un singolo campo di testo viene archiviato in un file binario come un numero fisso di byte con uno scostamento specificato in quel file binario. (Se un campo di testo ha meno caratteri, i restanti byte sono impostati su 0.)

Esistono numerosi sviluppatori (in diverse organizzazioni interne) che sono coinvolti nel mantenimento e nell'aggiunta di nuove funzionalità a tutti i programmi che costituiscono questa applicazione.

Uno dei problemi cronici che trattiamo è il codice che i confronti tra stringhe spesso falliscono perché il campo memorizzato può avere o meno spazi bianchi finali, a seconda di come quel campo specifico viene inserito e scritto nel file binario, e la stringa nel il codice che viene confrontato non lo fa. (In quasi tutti i casi, lo spazio vuoto finale non è considerato parte del valore del campo di testo).

Ci sono diversi approcci che possiamo adottare per affrontare questa situazione:

  1. Adotta una convenzione per tutti i campi memorizzati in un file binario deve essere tagliato prima di essere scritto.

  2. Adotta una convenzione che quando si confronta il testo dovrebbe essere il confronto     essere eseguito con le stringhe tagliate.

  3. Esegui sia (1) sia (2).

Ci sono dei vantaggi misurabili che suggeriscono che uno degli approcci precedenti è migliore di qualsiasi altro approccio. L'obiettivo generale è ridurre il numero di istanze di un errore dell'applicazione causato da spazi bianchi finali.

Nota - Attualmente stiamo facendo (2), ma di recente abbiamo trovato il codice legacy che non ignorava gli spazi bianchi finali.

    
posta Jay Elston 16.11.2016 - 19:35
fonte

4 risposte

3

Con più team e sviluppatori, non puoi aspettarti che tutti passino a una nuova convention immediatamente e in modo impeccabile. E ovviamente non puoi aspettarti che ogni app legacy venga cambiata immediatamente secondo una nuova convenzione. Quindi la cosa migliore è IMHO, ogni volta che devi sviluppare una nuova applicazione o modificare un'applicazione esistente, segui il principio di robustezza :

Be conservative in what you do, be liberal in what you accept from others.

Per il tuo caso - per ogni attributo in cui gli spazi finali devono essere ignorati - questo significa chiaramente l'opzione (3), fai entrambi:

  • (1) è "essere prudente in quello che fai" - tagliare gli spazi finali scritti come output in modo che altre applicazioni che accettano quelle stringhe funzionino anche se non sono pronte.

  • (2) è ciò che significa "essere liberali in ciò che si accetta dagli altri". Ogni volta che la tua applicazione ottiene quelle stringhe, aspettati che non vengano ritagliate in anticipo.

Ovviamente, fare (1) e (2) potrebbe sembrare superfluo a prima vista, ma nei sistemi più grandi con più componenti, la robustezza è un fattore chiave per mantenere il sistema scalabile.

    
risposta data 17.11.2016 - 10:41
fonte
1

Tutto dipende dalla potenziale rilevanza degli spazi bianchi finali nel dominio dell'applicazione.

Gli spazi bianchi finali possono essere dati pertinenti?

Se il tuo software è ad esempio un editor grafico, gli spazi trailing possono essere rilevanti: l'utente può inserire etichette centrate o allineate a destra e aggiungere spazi finali con intento (ad esempio per ottenere alcuni effetti di allineamento).

In questo caso, non rimuovere gli spazi finali da soli. Quindi l'attuale approccio 2 sarebbe il più consigliabile.

O gli spazi finali sono irrilevanti?

In molte applicazioni aziendali, gli spazi finali alla fine del campo non sono rilevanti (ad esempio, abitudini di input dell'utente).

In questo caso, consiglierei di tagliare costantemente gli spazi finali con l'opzione 1, perché in realtà questi spazi non appartengono ai dati. Non è solo il confronto, ma anche la formattazione e la combinazione, che potrebbero essere compromessi se si conservano i trailer.

Se non hai un controllo sufficiente su tutti i programmi che scrivono i dati, devi prepararti ad affrontare un mondo inaffidabile e scegliere l'opzione 3 per rendere il tuo codice resiliente. Lo stesso se per ragioni storiche non è possibile aggiornare i dati legacy (ad esempio se alcuni codici hash o la firma attestano la loro autenticità).

    
risposta data 16.11.2016 - 23:35
fonte
1

Dovresti:

a) Avere una qualche forma di interfaccia astratta per leggere e scrivere file, in modo che il codice per leggere e scrivere il file sia contenuto in un posto e non sparsi ovunque

b) avere un documento "relativamente formale" che descrive il formato del file; incluso specificare una codifica di caratteri specifica (ASCII? UTF-8?), quali caratteri sono legali / illegali (campana? elimina? scheda verticale e orizzontale?) e dove sono legali / illegali.

c) Includere un "numero di versione" nel file binario; in modo che se il formato del file cambia il numero di versione cambia. Ciò consente di (nella peggiore delle ipotesi) segnalare un errore se il formato del file non è compatibile con il codice corrente; o (nella migliore delle ipotesi) consentire il codice che legge i file per supportare più versioni del formato file (per "future retrocompatibilità").

d) Supponiamo che qualsiasi utente possa deliberatamente manomettere il file binario (ad esempio usando un editor esadecimale o qualcosa del genere) o manomettere accidentalmente il file binario (ad esempio cercando di risparmiare tempo modificandolo in un editor di testo); e usare pratiche di codifica difensive per evitare questo; incluso un ampio controllo degli errori in tutto il codice che legge / analizza il file e include messaggi di errore leggibili dettagliati per ogni caso in cui è possibile che i dati effettivi del file (dopo la manomissione) non siano conformi alle specifiche del formato del file.

    
risposta data 17.11.2016 - 09:37
fonte
0

Esistono numerosi approcci comuni.

  • Memorizza la stringa riempita con valori null. (Semplifica determinare se la stringa termina prima della fine del campo.)
  • Prefix la stringa con una lunghezza di testo binario. (Può essere efficiente in termini di spazio se il campo successivo viene seguito immediatamente, ma problematico per stringhe più lunghe di 255 byte).
  • Spazio spazia la stringa alla lunghezza del campo. (Non funziona bene se lo spazio finale può essere rilevante.)

Se gli spazi iniziali o finali non sono significativi, potrebbe essere opportuno tagliare la stringa prima dello stoccaggio.

Sembra che tu abbia preso la prima opzione che ho presentato, ma ritagliare gli spazi prima che la memorizzazione non sia stata applicata in modo affidabile. In questo caso sarebbe opportuno che i confronti tra stringhe ignorino lo spazio finale.

    
risposta data 17.11.2016 - 01:45
fonte

Leggi altre domande sui tag