¿Un valor centinela Unicode que puedo usar?

14

Estoy diseñando un formato de archivo y quiero hacerlo bien. Como es un formato binario, el primer byte (o bytes) del archivo no debe formar caracteres de texto válidos (como en el encabezado 1 del archivo PNG ). Esto permite que las herramientas que no reconocen el formato sigan viendo que no se trata de un archivo de texto al observar los primeros bytes.

Cualquier punto de código anterior 0x7Fes US-ASCII no válido, por lo que es fácil. Pero para Unicode es una historia completamente diferente. Aparte de caracteres Unicode válidos existen caracteres de uso privado , noncharacters y centinelas , ya que encontramos en los Unicode privado utiliza caracteres, Noncharacters y centinelas FAQ .

¿Cuál sería una secuencia de bytes centinela que puedo usar al comienzo del archivo que resultaría en US-ASCII, UTF-8, UTF-16LE y UTF-16BE no válidos?

  • Obviamente, el primer byte no puede tener un valor inferior, 0x80ya que sería un carácter US-ASCII (control) válido, por 0x00lo que no se puede usar.
  • Además, dado que los caracteres de uso privado son caracteres Unicode válidos, tampoco puedo usar esos puntos de código.
  • Dado que debe funcionar con UTF-16 little-endian y big-endian, un no carácter como 0xFFFEtampoco es posible ya que su reverso 0xFEFFes un carácter Unicode válido.
  • Las preguntas frecuentes mencionadas anteriormente sugieren no usar ninguno de los no caracteres, ya que eso aún generaría una secuencia Unicode válida, por lo que algo como eso 0xFFFFtambién está fuera de la imagen.

¿Cuáles serían los valores centinela a prueba de futuro que me quedan para usar?


1 ) El formato PNG tiene como primer byte el 0x89valor no ASCII , seguido de la cadena PNG. Una herramienta que lee los primeros bytes de un PNG puede determinar que es un archivo binario ya que no puede interpretarlo 0x89. Un archivo GIF, por otro lado, comienza directamente con la cadena ASCII válida y legible GIFseguida de tres caracteres ASCII más válidos. Para GIF, una herramienta puede determinar que es un archivo de texto legible. Esto está mal y la idea de iniciar el archivo con una secuencia de bytes no textural surgió de Designing File Formats de Andy McFadden.

Daniel AA Pelsmaeker
fuente
3
Since it is a binary format, the first bytes of the file should not form valid textual characters- Debería mirar el archivo mágico (/ usr / share / magic o / etc / magic en muchos sistemas unix) que muestra cómo esta aplicación identifica los tipos de archivos. Un archivo PNG comienza con \x89PNG\x0d\0a\x1a\x0a- tenga en cuenta el "PNG" allí, que es una cadena sin formato. Las secuencias \x89y similares son bytes no imprimibles.
@MichaelT Sí, dado que PNG es un formato binario, el primer byte no forma un carácter textual válido. A eso me refería. ¿No entiendo su punto de vista?
Daniel AA Pelsmaeker
77
Ese fue un ejemplo. Un .gif comienza con GIF8. Un archivo SGI movi comienza con MOVI. Un estilo de archivo zip comienza con ZZel formato pkzip más popular PK. La restricción de que el primer byte sea un carácter de texto no válido no parece coincidir con lo que se encuentra en la naturaleza. Tengo curiosidad por qué esto es un requisito.
3
¿Realmente te importa cómo se comportan otros programas cuando ven un archivo desconocido? Para mí, una secuencia de firma (como archivos PNG) es mucho más útil que una secuencia centinela: cuando el contenido se envía a través de un protocolo de flujo simple, el receptor puede decidir de inmediato cómo manejar los siguientes bytes. Una secuencia de centinela omaní está próxima a la no secuencia una vez que todos comienzan a usarla para identificar su propio formato.
Codismo
2
@Virtlink, no me importa particularmente qué bytes usas en tu formato de archivo. Pero usted hizo una afirmación de que es 'incorrecto' usar caracteres ascii ... sin embargo, no he visto nada aquí que respalde esa afirmación, y hay mucha experiencia empírica que muestra que realmente no importa (es decir, el innumerable archivo formatos que han estado utilizando caracteres ASCII sin problemas durante décadas)
GrandmasterB

Respuestas:

16

0xDC 0xDC

  • Obviamente inválido UTF-8 y ASCII
  • Sustituto de pista no emparejado en posición de liderazgo, independientemente de la resistencia en UTF-16. No obtiene más UTF-16 inválido que eso.
Esailija
fuente
Pero perfectamente razonable ISO-8859-1, y probablemente razonable en cualquier otro conjunto de caracteres que utilice una codificación de 8 bits.
parsifal
44
+1 OP no solicitó ISO 8859-1, solo US-ASCII y UTF- *.
Ross Patterson
@RossPatterson: cierto, pero sospecho que se debe principalmente a que el OP no ha pensado realmente en el problema. Sin ninguna estadística que me respalde, estoy dispuesto a apostar que un algoritmo aleatorio "es este texto" tiene más probabilidades de dar preferencia a ISO-8859-1 que a UTF-16, simplemente porque hay una enorme cantidad de 8 bits Texto en el mundo.
parsifal
3
@parsifal Cualquier binario es válido ISO-8859-1, por lo que no es necesario tenerlo en cuenta simplemente porque es imposible invalidar ISO-8859-1.
Esailija
1
@parsifal true y si ese fuera el requisito, podría usarlo 0x00o lo que sea, pero op no quería eso.
Esailija
5
  • En UTF-8, los bytes C0, C1 y F5 - FF son ilegales. El primer byte debe ser ASCII o un byte en el rango C2-F4, cualquier otro byte inicial no es válido UTF-8.

  • En UTF-16, el archivo normalmente comienza con la marca de orden de bytes (U + FEFF), de lo contrario las aplicaciones tienen que adivinar el orden de bytes. Los puntos de código en el rango D800-DBFF son bytes iniciales para un par sustituto, y DC00-DFFF son los bytes finales para un par sustituto.

Por lo tanto, usaría el byte combo F5DC. Estos dos valores son:

  • No ASCII
  • No válido UTF-8
  • Interpretado como un byte final UTF-16 en un par sustituto (no legal), o el punto de código U + F5DC, que es un carácter de uso privado, pero solo por aplicaciones que tercamente interpretan esto como UTF-16 incluso sin una lista de materiales .

Si necesita más opciones, F5DDa través de F5DFtodos tienen las mismas propiedades 3, al igual que F6DC- F6DF, F7DC- F7DFy F8DC- F8DF, para un total de 16 combinaciones de bytes diferentes para elegir.

Martijn Pieters
fuente
Entonces, por la sugerencia de Esailija de usar U + DCDC, 0xDC¿sería válido UTF-8?
Daniel AA Pelsmaeker
2
@Virtlink 0xDCes un byte principal UTF-8 para una secuencia de 2 bytes. Debe ser seguido por un 10xxxxxxbyte de continuación para que sea válido. 0xDCno es un byte de continuación válido, por 0xDC 0xDClo que no es válido UTF-8.
Esailija
@Virtlink: No, porque el segundo byte no es válido, debería estar en el rango 80- BF.
Martijn Pieters
2

Si está intentando utilizar un carácter no imprimible para indicar "no texto", le resultará difícil superar 0x89:

  • Está fuera del rango US-ASCII
  • En ISO-8859-1 es un carácter no imprimible ("TABULACIÓN DE CARACTERES CON JUSTIFICACIÓN"). Del mismo modo con Shift-JIS, que creo que todavía es de uso común. Sin embargo, otras codificaciones de 8 bits pueden tratar esto como un carácter válido.
  • En UTF-8 es un primer byte no válido para una secuencia de varios bytes (los bits superiores son 10, que están reservados para los caracteres 2..N de una secuencia de varios bytes)

En general, cuando forma números mágicos, "sin texto" es un punto menor. Tendré que buscar la referencia, pero uno de los formatos gráficos estándar (TIFF, creo) tiene algo así como seis piezas diferentes de información útil de su número mágico.

parsifal
fuente