Une valeur sentinelle Unicode que je peux utiliser?

14

Je conçois un format de fichier et je veux le faire correctement. Puisqu'il s'agit d'un format binaire, le tout premier octet (ou octets) du fichier ne doit pas former de caractères textuels valides (comme dans l'en-tête de fichier PNG 1 ). Cela permet aux outils qui ne reconnaissent pas le format de voir que ce n'est pas un fichier texte en regardant les premiers octets.

Tout point de code ci 0x7F- dessus n'est pas valide US-ASCII, donc c'est facile. Mais pour Unicode, c'est une toute autre histoire. En dehors de caractères Unicode valides il y a des caractères à usage privé , non - caractères et factionnaires , comme je l' ai trouvé dans les caractères Unicode Private-utilisation, et Sentinelles FAQ non - caractères .

Quelle serait une séquence sentinelle d'octets que je pourrais utiliser au début du fichier qui résulterait en US-ASCII, UTF-8, UTF-16LE et UTF-16BE invalides?

  • De toute évidence, le premier octet ne peut pas avoir une valeur inférieure 0x80car ce serait un caractère US-ASCII (contrôle) valide, il 0x00ne peut donc pas être utilisé.
  • De plus, comme les caractères à usage privé sont des caractères Unicode valides, je ne peux pas non plus utiliser ces points de code.
  • Puisqu'il doit fonctionner à la fois avec le petit endian et le big-endian UTF-16, un non- caractère tel que celui-ci 0xFFFEn'est également pas possible car son inverse 0xFEFFest un caractère Unicode valide.
  • La FAQ mentionnée ci-dessus suggère de n'utiliser aucun des non- caractères car cela entraînerait toujours une séquence Unicode valide, donc quelque chose comme 0xFFFFest également hors de l'image.

Quelles seraient les valeurs sentinelles à l'épreuve du temps qui me resteraient à utiliser?


1 ) Le format PNG a comme tout premier octet la 0x89valeur non ASCII , suivie de la chaîne PNG. Un outil qui lit les premiers octets d'un PNG peut déterminer qu'il s'agit d'un fichier binaire car il ne peut pas l'interpréter 0x89. Un fichier GIF, en revanche, commence directement par la chaîne ASCII valide et lisible GIFsuivie de trois autres caractères ASCII valides. Pour GIF, un outil peut déterminer qu'il s'agit d'un fichier texte lisible. C'est faux et l'idée de démarrer le fichier avec une séquence d'octets non texturée est venue de Designing File Formats par Andy McFadden.

Daniel AA Pelsmaeker
la source
3
Since it is a binary format, the first bytes of the file should not form valid textual characters- Vous devriez regarder le fichier magique (/ usr / share / magic, ou / etc / magic sur de nombreux systèmes Unix) qui montre comment cette application identifie les types de fichiers. Un fichier PNG commence par \x89PNG\x0d\0a\x1a\x0a- notez le "PNG" là-dedans, c'est une chaîne brute. Les séquences \x89et similaires sont des octets non imprimables.
@MichaelT Oui, puisque PNG est un format binaire, le premier octet ne forme pas un caractère textuel valide. C'est ce que je voulais dire. Je ne vois pas votre point?
Daniel AA Pelsmaeker
7
C'était un exemple. Un .gif commence par GIF8. Un fichier SGI movi commence par MOVI. Un style de fichier d'archive zip commence par ZZ, le format pkzip plus populaire commence par PK. La contrainte que le premier octet soit un caractère de texte non valide ne semble pas correspondre à ce qui se trouve dans la nature. Je suis curieux de savoir pourquoi c'est une exigence.
3
Vous souciez-vous vraiment du comportement des autres programmes lorsqu'ils voient un fichier inconnu? Pour moi, une séquence de signature (comme les fichiers PNG) est beaucoup plus utile qu'une séquence sentinelle - lorsque le contenu est envoyé via un protocole de flux simple, le récepteur peut immédiatement décider comment gérer les octets suivants. Une séquence sentinelle omanaise est pratiquement sans séquence une fois que tout le monde commence à l'utiliser pour identifier son propre format.
Codism
2
@Virtlink, peu m'importe quels octets vous utilisez dans votre format de fichier. Mais vous avez affirmé que son «mauvais» d'utiliser des caractères ascii ... pourtant je n'ai rien vu ici qui soutient cette affirmation, et il y a beaucoup d'expérience empirique qui montre que cela n'a vraiment pas d'importance (c'est-à-dire, le nombre incalculable de fichiers formats qui utilisent des caractères ASCII sans problème depuis des décennies)
GrandmasterB

Réponses:

16

0xDC 0xDC

  • Évidemment UTF-8 et ASCII non valides
  • Substitut de piste non apparié en position de tête indépendamment de l'endianisme en UTF-16. Il n'obtient pas plus UTF-16 invalide que cela.
Esailija
la source
Mais ISO-8859-1 parfaitement raisonnable, et probablement raisonnable dans tout autre jeu de caractères utilisant un encodage 8 bits.
parsifal
4
+1 OP n'a pas demandé ISO 8859-1, juste US-ASCII et UTF- *.
Ross Patterson
@ RossPatterson - vrai, mais je suppose que c'est principalement parce que l'OP n'a pas vraiment réfléchi au problème. Sans aucune statistique pour me soutenir, je suis prêt à parier qu'un algorithme aléatoire "est ce texte" est plus susceptible de donner la préférence à ISO-8859-1 qu'à UTF-16, simplement parce qu'il y a une énorme quantité de 8 bits texte dans le monde.
parsifal
3
@parsifal Tout binaire est ISO-8859-1 valide, il n'a donc pas besoin d'être pris en compte simplement parce qu'il est impossible de rendre ISO-8859-1 invalide.
Esailija
1
@parsifal true et si c'était l'exigence que vous pourriez simplement utiliser 0x00ou autre chose, mais op ne voulait pas cela.
Esailija
5
  • En UTF-8, les octets C0, C1 et F5 - FF sont illégaux. Le premier octet doit être ASCII ou un octet dans la plage C2-F4, tout autre octet de départ n'est pas UTF-8 valide.

  • En UTF-16, le fichier commence normalement par la marque d'ordre des octets (U + FEFF), sinon les applications doivent deviner l'ordre des octets. Les points de code de la plage D800-DBFF sont des octets de tête pour une paire de substitution, et DC00-DFFF sont les octets de fin pour une paire de substitution.

Ainsi, j'utiliserais le combo d'octets F5DC. Ces deux valeurs sont:

  • Pas ASCII
  • UTF-8 non valide
  • Soit interprété comme un octet de fin UTF-16 dans une paire de substitution (non légal), soit le point de code U + F5DC, qui est un caractère à usage privé, mais uniquement par des applications qui tentent obstinément d'interpréter cela comme UTF-16 même sans nomenclature .

Si vous avez besoin de plus d' options, F5DDpar le biais de F5DFtous les mêmes propriétés 3, tout comme F6DC- F6DF, F7DC- F7DFet F8DC- F8DF, pour un total de 16 combinaisons d'octets différents à choisir.

Martijn Pieters
la source
Donc, par la suggestion d' Esailija d'utiliser U + DCDC, 0xDCserait-il valide UTF-8?
Daniel AA Pelsmaeker
2
@Virtlink 0xDCest un octet de tête UTF-8 pour une séquence de 2 octets. Il doit être suivi d'un 10xxxxxxoctet de continuation pour qu'il soit valide. 0xDCn'est pas un octet de continuation valide, donc 0xDC 0xDCn'est pas valide UTF-8.
Esailija
@Virtlink: Non, car le deuxième octet n'est pas valide, il devrait être dans la plage 80- BF.
Martijn Pieters
2

Si vous essayez d'utiliser un caractère non imprimable pour indiquer «pas de texte», vous aurez du mal à battre 0x89:

  • C'est en dehors de la gamme US-ASCII
  • Dans ISO-8859-1, il s'agit d'un caractère non imprimable ("TABULATION DE CARACTÈRE AVEC JUSTIFICATION"). De même avec Shift-JIS, qui, je crois, est encore couramment utilisé. D'autres codages 8 bits peuvent cependant traiter cela comme un caractère valide.
  • En UTF-8, c'est un premier octet invalide pour une séquence multi-octets (les bits supérieurs sont 10, qui sont réservés aux caractères 2..N d'une séquence multi-octets)

Généralement, lorsque vous formez des nombres magiques, le «non-texte» est un point mineur. Je vais devoir chercher la référence, mais l'un des formats graphiques standard (TIFF, je pense) a quelque chose comme six informations différentes de son numéro magique.

parsifal
la source