Domanda

Informalmente, la maggior parte di noi capire che non ci sono file 'binari' (file oggetti, immagini, filmati, file eseguibili, formati di documenti proprietari, ecc) e file di 'testo' (codice sorgente, file XML, file HTML, e-mail, ecc ).

In generale, è necessario conoscere il contenuto di un file per essere in grado di fare qualcosa di utile con esso, e formare quel punto di vista, se la codifica è 'binaria' o 'testo', non ha molta importanza. E, naturalmente, i file appena memorizzare byte di dati in modo che siano tutte 'binario' e 'text' non significa nulla senza conoscere la codifica. E tuttavia, è ancora utile parlare di file 'binari' e 'testo', ma per evitare di offendere nessuno con questa definizione imprecisa, io continuerò a usare le virgolette 'spaventare'.

Tuttavia, ci sono diversi strumenti che lavorano su una vasta gamma di file, e in termini pratici, si vuole fare qualcosa di diverso a seconda che il file è 'testo' o 'binario'. Un esempio di questo è qualsiasi strumento che emette i dati sulla console. Plain 'testo' sarà guardare bene, ed è utile. dati 'binario' scombina il terminale, ed è generalmente non è utile a guardare. GNU grep almeno usa questa distinzione per determinare se si deve partite output alla console.

Quindi, la domanda è: come si fa a dire se un file è 'testo' o 'binario'? E per limitare ulteriormente, come si fa a dire su un Linux come file-system? Non sono a conoscenza di alcun meta-dati di file system che indica il 'tipo' di un file, in modo che la questione diventa ulteriormente, controllando il contenuto di un file, come faccio a sapere se si tratta di 'testo' o 'binario'? E per semplicità, consente di limitare 'testo' per indicare i caratteri che sono stampabili sulla console dell'utente. E, in particolare, come si sarebbe implementare questo? (Ho pensato che questo era implicito su questo sito, ma credo che sia utile, in generale, deve essere puntato verso il codice esistente che fa questo, avrei dovuto specificato), io non sono davvero dopo quello che i programmi esistenti possono utilizzare per fare questo.

È stato utile?

Soluzione

Il software foglio di calcolo la mia azienda fa legge un certo numero di formati di file binari e file di testo.

Per prima cosa guardiamo i primi byte per un numero magico che noi riconoscere. Se non riconosciamo il numero magico di uno dei tipi di binari che abbiamo letto, poi guardiamo fino ai primi 2K byte del file per vedere se sembra essere un UTF-8 , UTF-16 o un file di testo codificato nei href="http://en.wikipedia.org/wiki/Code_page" pagina di codice di il sistema operativo host. Se passa nessuno di questi test, si assume che non si tratta di un file che possiamo affrontare e un'eccezione appropriata.

Altri suggerimenti

È possibile utilizzare il comando file. Si fa un po 'di prove su file (man file) per decidere se è binario o di testo. Potete guardare / prendere in prestito il suo codice sorgente, se avete bisogno di farlo da C.

file README
README: ASCII English text, with very long lines

file /bin/bash
/bin/bash: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), stripped

È possibile determinare il tipo MIME del file con

file --mime FILENAME

La stenografia è file -i su Linux e file -I (capitale i) su MacOS (vedi commenti).

Se inizia con text/, è il testo, altrimenti binario. L'unica eccezione sono le applicazioni XML. È possibile abbinare quelli cercando per +xml alla fine del tipo di file.

Beh, se sono solo ispeziona l'intero file, vedere se ogni carattere è stampabile con isprint(c). Si diventa un po 'più complicato per Unicode.

Per distinguere un file di testo Unicode, MSDN offre alcuni ottimi consigli su cosa fare .

L'essenza di esso è di ispezionare prima fino ai primi quattro byte:

EF BB BF     UTF-8 
FF FE        UTF-16, little endian 
FE FF        UTF-16, big endian 
FF FE 00 00  UTF-32, little endian 
00 00 FE FF  UTF-32, big-endian 

Che vi dirà la codifica. Poi, che ci si vuole utilizzare iswprint(c) per il resto dei personaggi nel file di testo. Per UTF-8 e UTF-16, è necessario analizzare i dati manualmente poiché un singolo carattere può essere rappresentato da un numero variabile di byte. Inoltre, se siete veramente anale, ti consigliamo di utilizzare la variante locale del iswprint se è disponibile sulla propria piattaforma.

Perl ha un'euristica decente. Utilizzare l'operatore -B per verificare binaria (e il suo opposto, -T per testare per il testo). Qui di shell un one-liner per elencare i file di testo:

$ find . -type f -print0 | perl -0nE 'say if -f and -s _ and -T _'

(Si noti che queste sottolineature senza un dollaro precedente sono corrette (RTFM).)

La maggior parte dei programmi che cercano di capire la differenza utilizzare un euristica, come ad esempio esaminando le prime n byte del file e vedere se quei byte tutti si qualifica come 'testo' o no (cioè, fanno tutti rientrano all'interno della gamma di charcters ASCII stampabili). Per distiction più fine c'è sempre il comando 'file' sui sistemi UNIX-like.

Il suo vecchio argomento, ma forse qualcuno troverà questo utile. Se si deve decidere in uno script se qualcosa è un file allora si può semplicemente fare in questo modo:

if file -i $1 | grep -q text;
then 
.
.
fi

In questo modo ottenere il tipo di file, e con un grep silenziosa si può decidere se un testo.

Per elencare i nomi dei file di testo nella directory corrente / sottodirectory:

$ grep -rIl ''

binari:

$ grep -rIL ''

Per controllare particolare file, modificare leggermente il comando:

$ grep -qI '' FILE

dunque, stato di uscita '0' significherebbe il file è un testo; '1' - binario. Potrebbe verificare:

$ echo $?

Un semplice controllo è se è \0 caratteri. I file di testo non li hanno.

* nix sistemi operativi precedentemente affermato hanno questa capacità all'interno del comando file. Questo comando utilizza un file di configurazione che definisce numeri magici contenuti in molte strutture di file popolari.

Questo file, denominato magia era storicamente conservato in / etc, anche se questo può essere in / usr / share in alcune distribuzioni. Il magic file definisce offset di valori noti di esistere all'interno del file e possono quindi esaminare questi luoghi per determinare il tipo di file.

La struttura e la descrizione del file magia si possono trovare consultando la pagina di manuale relativa (uomo magico)

Per quanto riguarda un'implementazione, e che possono essere trovate all'interno file.c per sé, tuttavia la quota di competenza del comando file che determina se si tratta di testo leggibile o non è il seguente

/* Make sure we are dealing with ascii text before looking for tokens */
    for (i = 0; i < nbytes - 1; i++) {
        if (!isascii(buf[i]) ||
            (iscntrl(buf[i]) && !isspace(buf[i]) &&
             buf[i] != '\b' && buf[i] != '\032' && buf[i] != '\033'
            )
           )
            return 0;   /* not all ASCII */
    }

È possibile utilizzare libmagic che è una versione biblioteca della riga di comando di Unix file.

Ci sono wrapper per molte lingue:

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top