Um valor de sentinela Unicode que posso usar?

14

Estou projetando um formato de arquivo e quero fazê-lo corretamente. Por ser um formato binário, o primeiro byte (ou bytes) do arquivo não deve formar caracteres textuais válidos (como no cabeçalho do arquivo PNG 1 ). Isso permite que as ferramentas que não reconhecem o formato ainda vejam que não é um arquivo de texto observando os primeiros bytes.

Qualquer ponto de código acima 0x7Fé US-ASCII inválido, portanto é fácil. Mas para Unicode é uma história totalmente diferente. Além dos caracteres Unicode válidos, existem caracteres de uso privado , não caracteres e sentinelas , como encontrei nas Perguntas frequentes sobre caracteres de uso privado Unicode, não caracteres e sentinelas .

O que seria uma sequência sentinela de bytes que eu possa usar no início do arquivo que resultaria em US-ASCII, UTF-8, UTF-16LE e UTF-16BE inválidos?

  • Obviamente, o primeiro byte não pode ter um valor abaixo, 0x80pois seria um caractere US-ASCII (controle) válido, portanto, 0x00não pode ser usado.
  • Além disso, como os caracteres de uso privado são caracteres Unicode válidos, também não posso usar esses pontos de código.
  • Como ele deve funcionar com UTF-16 little-endian e big-endian, um não caractere como 0xFFFEtambém não é possível, pois seu inverso 0xFEFFé um caractere Unicode válido.
  • As perguntas frequentes acima mencionadas sugerem não usar nenhum dos não - caracteres, pois isso ainda resultaria em uma sequência Unicode válida; portanto, algo como 0xFFFFtambém está fora de cena.

Quais seriam os valores sentinela à prova de futuro que ainda restam para eu usar?


1 ) O formato PNG tem como primeiro byte o 0x89valor não ASCII , seguido pela string PNG. Uma ferramenta que lê os primeiros bytes de um PNG pode determinar que é um arquivo binário, pois não pode ser interpretado 0x89. Um arquivo GIF, por outro lado, começa diretamente com a sequência ASCII válida e legível, GIFseguida por mais três caracteres ASCII válidos. Para o GIF, uma ferramenta pode determinar que é um arquivo de texto legível. Isso está errado e a idéia de iniciar o arquivo com uma sequência de bytes não textuais veio de Designing File Formats, de Andy McFadden.

Daniel AA Pelsmaeker
fonte
3
Since it is a binary format, the first bytes of the file should not form valid textual characters- Você deve observar o arquivo mágico (/ usr / share / magic ou / etc / magic em muitos sistemas unix) que mostra como esse aplicativo identifica os tipos de arquivo. Um arquivo PNG começa com \x89PNG\x0d\0a\x1a\x0a- observe o "PNG", é uma string não processada. As sequências \x89e similares são bytes não imprimíveis.
@MichaelT Sim, como PNG é um formato binário, o primeiro byte não forma um caractere textual válido. Foi isso que eu quis dizer. Eu não consigo entender o seu ponto?
Daniel Daniel Pelsmaeker 13/03/2019
7
Esse foi um exemplo. Um gif começa com GIF8. Um arquivo SGI movi começa com MOVI. Um estilo de arquivo zip começa com ZZo formato pkzip mais popular PK. A restrição de que o primeiro byte seja um caractere de texto inválido não parece corresponder ao encontrado na natureza. Estou curioso para saber por que isso é um requisito.
3
Você realmente se importa com o comportamento de outros programas quando vêem um arquivo desconhecido? Para mim, uma sequência de assinatura (como arquivos PNG) é muito mais útil do que uma sequência sentinela - quando o conteúdo é enviado através de um protocolo de fluxo simples, o receptor pode decidir imediatamente como lidar com os seguintes bytes. Uma sequência de Omã-sentinela fica quase sem sequência quando todos começam a usá-la para identificar seu próprio formato.
Codism 13/03
2
@Virtlink, eu particularmente não me importo com os bytes que você usa no seu formato de arquivo. Mas você fez uma afirmação de que é "errado" usar caracteres ascii ... ainda não vi nada aqui que apóie essa afirmação, e há muita experiência empírica que mostra que realmente não importa (ou seja, o arquivo incontável formatos que usam caracteres ASCII sem problemas há décadas)
GrandmasterB

Respostas:

16

0xDC 0xDC

  • Obviamente, UTF-8 e ASCII inválidos
  • Substituto de trilha não emparelhado na posição de liderança, independentemente da endianess em UTF-16. Não obtém mais UTF-16 inválido do que isso.
Esailija
fonte
Mas perfeitamente razoável ISO-8859-1 e provavelmente razoável em qualquer outro conjunto de caracteres que use uma codificação de 8 bits.
parsifal
4
O +1 OP não solicitou a ISO 8859-1, apenas US-ASCII e UTF- *.
Ross Patterson
@ RossPatterson - é verdade, mas suspeito que seja principalmente porque o OP realmente não pensou no problema. Sem nenhuma estatística para me apoiar, estou disposto a apostar que um algoritmo aleatório "é este texto" tem mais probabilidade de dar preferência à ISO-8859-1 do que à UTF-16, simplesmente porque há uma quantidade enorme de 8 bits texto no mundo.
parsifal
3
@parsifal Qualquer binário é ISO-8859-1 válido, portanto não precisa ser considerado simplesmente porque é impossível tornar ISO-8859-1 inválido.
Esailija 14/03/2013
1
@parsifal true e se esse era o requisito, você poderia simplesmente usar 0x00ou qualquer outra coisa, mas a op não queria isso.
Esailija 14/03
5
  • No UTF-8, os bytes C0, C1 e F5 - FF são ilegais. O primeiro byte deve ser ASCII ou um byte no intervalo C2-F4; qualquer outro byte inicial não é válido UTF-8.

  • No UTF-16, o arquivo normalmente começa com a marca de ordem de bytes (U + FEFF), caso contrário, os aplicativos precisam adivinhar a ordem de bytes. Os pontos de código no intervalo D800-DBFF são bytes iniciais para um par substituto, e DC00-DFFF são os bytes finais para um par substituto.

Assim, eu usaria a combinação de bytes F5DC. Esses dois valores são:

  • Não ASCII
  • UTF-8 inválido
  • Interpretado como um byte à direita UTF-16 em um par substituto (não legal) ou o ponto de código U + F5DC, que é um caractere de uso privado, mas apenas por aplicativos que tentam teimosamente interpretar isso como UTF-16, mesmo sem uma lista técnica .

Se precisar de mais opções, F5DDatravés de F5DFtodos têm os mesmos 3 propriedades, como fazem F6DC- F6DF, F7DC- F7DFe F8DC- F8DF, para um total de 16 combos byte diferentes para escolher.

Martijn Pieters
fonte
Então, pela sugestão de Esailija de usar U + DCDC, 0xDCseria válido o UTF-8?
Daniel Daniel Pelsmaeker
2
O @Virtlink 0xDCé um byte de chumbo UTF-8 para uma sequência de 2 bytes. Ele deve ser seguido por um 10xxxxxxbyte de continuação para que seja válido. 0xDCnão é um byte de continuação válido, portanto, 0xDC 0xDCnão é um UTF-8 válido.
Esailija 13/03/2013
@Virtlink: Não, porque o segundo byte não é válido, ele teria que estar no intervalo 80- BF.
precisa
2

Se você estiver tentando usar um caractere não imprimível para indicar "não texto", será difícil superar 0x89:

  • Está fora da faixa US-ASCII
  • Na ISO-8859-1, é um caractere não imprimível ("TABELA DE CARÁTER COM JUSTIFICAÇÃO"). Da mesma forma, com o Shift-JIS, que acredito ainda ser de uso comum. Outras codificações de 8 bits podem, no entanto, tratar isso como um caractere válido.
  • No UTF-8, é um primeiro byte inválido para uma sequência de bytes múltiplos (os bits superiores são 10, reservados para os caracteres 2..N de uma sequência de bytes múltiplos)

Geralmente, quando você forma números mágicos, "não texto" é um ponto menor. Vou ter que procurar a referência, mas um dos formatos gráficos padrão (TIFF, eu acho) tem algo como seis diferentes informações úteis do seu número mágico.

parsifal
fonte