Comment faire la distinction entre les fichiers "binaires" et "texte"?
de manière informelle, la plupart d'entre nous comprennent qu'il existe des fichiers "binaires" (fichiers objets, images, films, exécutables, formats de documents propriétaires, etc.) et des fichiers "textuels" (code source, fichiers XML, fichiers HTML, courriels, etc.).
en général, vous devez connaître le contenu d'un fichier pour pouvoir faire quelque chose d'utile avec lui, et former ce point de vue si l'encodage est 'binaire' ou 'texte', il n'a pas vraiment d'importance. Et bien sûr, les fichiers stockent juste des octets de données afin qu'ils soient tout "binaire" et "texte" ne signifie rien sans connaître l'encodage. Et pourtant, il est toujours utile de parler de "binaire" et "texte" des fichiers, mais pour éviter d'offenser quiconque avec cette définition imprécise, je vais continuer à utiliser "faire peur" citations.
cependant, il existe divers outils qui fonctionnent sur un large éventail de fichiers, et en termes pratiques, vous voulez faire quelque chose de différent selon que le fichier est "texte" ou "binaire". Un exemple de ceci est tout outil qui produit des données sur la console. Plaine "texte" sera bien, et est utile. les données 'binaires' bousillent votre terminal, et ne sont généralement pas utiles à regarder. GNU grep utilise au moins cette distinction pour déterminer si la sortie doit correspondre à la console.
alors, la question Est, Comment savoir si un fichier est 'text' OU 'binaire'? Et pour restreindre est plus loin, comment dire sur un Linux comme le système de fichiers? Je ne connais pas de méta-données du système de fichiers qui indique le 'type' d'un fichier, donc le la question devient encore, en inspectant le contenu d'un fichier, comment puis-je savoir si c'est "texte" ou "binary"? Et pour plus de simplicité, limitons le "texte" aux caractères imprimables sur la console de l'utilisateur. Et en particulier comment mettre en œuvre ceci? (Je pensais que c'était implicite sur ce site, mais je suppose qu'il est utile, en général, d'être pointé sur le code existant qui fait cela, j'aurais dû préciser), Je ne suis pas vraiment après ce que les programmes existants peuvent je utiliser pour faire ce.
11 réponses
le logiciel de tableur mon entreprise fait lit un certain nombre de formats de fichier binaire ainsi que des fichiers texte.
Nous considérons d'abord les premiers octets d'un nombre magique que nous reconnaissons. Si nous ne reconnaissons pas le nombre magique de l'un des types binaires nous lire, puis on regarde jusqu'à la première 2K octets du fichier pour voir si elle semble être un UTF-8 , UTF-16 ou un fichier texte encodé dans l'actuelle page de code du système d'exploitation hôte. S'il ne passe aucun de ces tests, nous présumons qu'il ne s'agit pas d'un fichier que nous pouvons traiter et nous faisons une exception appropriée.
vous pouvez utiliser la commande file
. Il fait un tas de tests sur le fichier ( man file
) pour décider s'il est binaire ou texte. Vous pouvez consulter / emprunter son code source si vous avez besoin de le faire à partir de 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
vous pouvez déterminer le type MIME du fichier avec
file --mime FILENAME
L'abréviation est file -i
sur Linux et file -I
(le capital, i) sur macOS (voir les commentaires).
si ça commence par text/
, c'est du texte, sinon du binaire. Les applications XML constituent la seule exception. Vous pouvez les apparier en cherchant +xml
à la fin du type de fichier.
Eh bien, si vous inspectez juste le dossier entier, voir si chaque caractère est imprimable avec isprint(c)
. Ça devient un peu plus compliqué pour Unicode.
pour distinguer un fichier texte unicode, MSDN offre quelques bons conseils quant à ce qu'il faut faire .
L'essentiel, c'est d'abord inspecter les quatre premiers octets:
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
Qui vous indiquera l'encodage. Alors, vous voulez les utiliser iswprint(c)
pour le reste des caractères du fichier texte. Pour l'UTF-8 et UTF-16, vous devez analyser les données manuellement depuis un seul caractère peut être représenté par un nombre variable d'octets. En outre, si vous êtes vraiment anal, vous voudrez utiliser la variante locale de iswprint
si elle est disponible sur votre plate-forme.
Perl a un heuristique décent. Utilisez l'opérateur -B
pour tester le binaire (et son opposé, -T
pour tester le texte). Voici shell un one-liner pour lister les fichiers texte:
$ find . -type f -print0 | perl -0nE 'say if -f and -s _ and -T _'
(notez que ces soulignements sans un dollar précédent sont corrects (RTFM).)
la plupart des programmes qui essaient de faire la différence utilisent un heuristique, tel que l'examen du premier n bytes du fichier et de voir si ces bytes tous qualifient comme "texte" ou non (c.-à-d. sont-ils tous dans la gamme des charcters ASCII imprimables). Pour une répartition plus fine, il y a toujours la commande "file" sur les systèmes de type UNIX.
C'est un vieux sujet, mais peut-être que quelqu'un trouvera cela utile. Si vous devez décider dans un script si quelque chose est un fichier, alors vous pouvez simplement faire comme ceci:
if file -i | grep -q text;
then
.
.
fi
cela va obtenir le type de fichier, et avec un grep silencieux, vous pouvez décider si son un texte.
une vérification simple est de savoir s'il y a des caractères " 151900920"
. Les fichiers texte n'en ont pas.
comme indiqué précédemment *les systèmes d'exploitation nix ont cette capacité dans la commande file. Cette commande utilise un fichier de configuration qui définit les nombres magiques contenus dans de nombreuses structures de fichiers populaires.
ce fichier, appelé magic a été historiquement stocké dans /etc, Bien que cela puisse être dans /usr/share sur certaines distributions. Le fichier magic définit des offsets de valeurs connues pour exister dans le fichier et peut ensuite examiner ces emplacements pour déterminer le type de la fichier.
on peut trouver la structure et la description du fichier magic en consultant la page de manuel pertinente (man magic)
comme pour une implémentation, bien qui peut être trouvé dans le fichier .c elle-même, cependant la partie pertinente de la commande de fichier qui détermine si elle est Texte lisible ou non est la suivante
/* 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] != '2' && buf[i] != '3'
)
)
return 0; /* not all ASCII */
}
pour énumérer les noms de fichiers textuels dans les dir/sousdirs actuels:
$ grep -rIl ''
binaires:
$ grep -rIL ''
pour vérifier un fichier particulier, modifier légèrement la commande:
$ grep -qI '' FILE
alors, exit status ' 0 'signifierait que le fichier est un texte;' 1 ' - binaire.
$ echo $?