Comment faire la distinction entre les fichiers «binarys» et les fichiers «texte»?

Informellement, la plupart d’entre nous comprennent qu’il existe des fichiers «binarys» (fichiers objects, images, films, exécutables, formats de documents propriétaires, etc.) et des fichiers «texte» (code source, fichiers XML, fichiers HTML, e-mail, etc.).

En général, vous devez connaître le contenu d’un fichier pour pouvoir faire quelque chose d’utile et former ce sharepoint vue si le codage est “binary” ou “texte”, cela n’a pas vraiment d’importance. Et bien sûr, les fichiers stockent simplement des octets de données afin qu’ils soient tous «binarys» et que «texte» ne signifie rien sans connaître l’encodage. Et pourtant, il est toujours utile de parler de fichiers «binarys» et de fichiers «texte», mais pour ne pas offenser quiconque avec cette définition imprécise, je continuerai à utiliser des citations «effrayantes».

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 «binary». Un exemple de ceci est tout outil qui produit des données sur la console. Le texte simple sera correct et utile. Les données «binarys» gâchent 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 de savoir comment savoir si un fichier est «texte» ou «binary». Et pour limiter est plus loin, comment racontez-vous sur un Linux comme un système de fichiers? Je ne suis au courant d’aucune méta-donnée de système de fichiers qui indique le “type” d’un fichier. La question devient donc, en inspectant le contenu d’un fichier, comment savoir si c’est un “texte” ou un “binary”? Et pour simplifier, limitons le “texte” à des caractères imprimables sur la console de l’utilisateur. Et en particulier comment metsortingez-vous en œuvre cela? (Je pensais que cela était implicite sur ce site, mais je pense qu’il est utile, en général, d’être orienté vers le code existant qui le fait, j’aurais dû le préciser), je ne suis pas vraiment au courant des programmes existants ce.

Le tableur que ma société fabrique lit un certain nombre de formats de fichiers binarys ainsi que des fichiers texte.

Nous examinons 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 binarys que nous lisons, nous examinons les 2 premiers octets du fichier pour voir s’il semble s’agir d’un fichier UTF-8 , UTF-16 ou d’un fichier texte codé. dans la page de codes actuelle du système d’exploitation hôte. S’il ne passe aucun de ces tests, nous supposons qu’il ne s’agit pas d’un fichier avec lequel nous pouvons traiter et lancer une exception appropriée.

Vous pouvez utiliser la commande file . Il fait un tas de tests sur le fichier (fichier man file ) pour décider si c’est du binary ou du texte. Vous pouvez regarder / emprunter son code source si vous devez 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), ssortingpped 

Vous pouvez déterminer le type MIME du fichier avec

 file --mime FILENAME 

Le raccourci est file -i sur Linux et file -I (majuscule i) sur macOS (voir commentaires).

Si cela commence par text/ , c’est du texte, sinon binary. Les seules exceptions sont les applications XML. Vous pouvez faire correspondre ceux en recherchant +xml à la fin du type de fichier.

Eh bien, si vous inspectez tout le fichier, voyez si chaque caractère est imprimable avec isprint(c) . Cela devient un peu plus compliqué pour Unicode.

Pour distinguer un fichier texte unicode, MSDN offre de bons conseils quant à la marche à suivre .

L’essentiel est d’inspecter d’abord 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 

Cela vous dira l’encodage. Ensuite, vous souhaitez utiliser iswprint(c) pour le rest des caractères du fichier texte. Pour UTF-8 et UTF-16, vous devez parsingr les données manuellement car un seul caractère peut être représenté par un nombre variable d’octets. De plus, si vous êtes vraiment anal, vous voudrez utiliser la variante locale de iswprint si celle-ci est disponible sur votre plate-forme.

Perl a une heuristique décente. Utilisez l’opérateur -B pour tester le binary (et son contraire, -T pour tester le texte). Voici un shell pour lister les fichiers texte:

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

(Notez que ces traits de soulignement sans un dollar précédent sont corrects (RTFM).)

La plupart des programmes qui essaient de faire la différence utilisent une heuristique, par exemple en examinant les n premiers octets du fichier et en vérifiant si ces octets sont tous qualifiés de “texte” ou non (ils entrent tous dans la plage des caractères ASCII imprimables) . Pour une distorsion plus fine, il y a toujours la commande ‘file’ sur les systèmes 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, vous pouvez simplement faire comme ceci:

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

Cela permet d’obtenir le type de fichier et, avec un grep silencieux, vous pouvez décider s’il s’agit d’un texte.

Une simple vérification est si il a \0 caractères. Les fichiers texte ne les ont pas.

Comme indiqué précédemment, les systèmes d’exploitation nix ont cette possibilité dans la commande de fichier. Cette commande utilise un fichier de configuration qui définit des nombres magiques contenus dans de nombreuses structures de fichiers populaires.

Ce fichier, appelé magic, était historiquement stocké dans / etc, bien que cela puisse être dans / usr / share sur certaines dissortingbutions. Le fichier magique définit des décalages de valeurs connus pour exister dans le fichier et peut ensuite examiner ces emplacements pour déterminer le type du fichier.

La structure et la description du fichier magique peuvent être trouvées en consultant la page de manuel correspondante (man magic)

En ce qui concerne une implémentation, eh bien, cela peut être trouvé dans fichier.c lui-même, cependant la partie pertinente de la commande de fichier qui détermine si c’est du 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] != '\032' && buf[i] != '\033' ) ) return 0; /* not all ASCII */ } 

Vous pouvez utiliser libmagic qui est une version de bibliothèque de la ligne de commande de file Unix.

Il existe un wrapper pour de nombreuses langues:

  • Python
  • .NET
  • Nodejs
  • Rubis
  • Aller

Pour lister les noms de fichiers texte dans le répertoire / sous répertoire actuel:

 $ grep -rIl '' 

Binaires:

 $ grep -rIL '' 

Pour vérifier un fichier particulier, modifiez légèrement la commande:

 $ grep -qI '' FILE 

alors, le statut de sortie “0” signifierait que le fichier est un texte; ‘1’ – binary. Pourrait vérifier:

$ echo $?