我可以使用Unicode哨兵值吗?


14

我正在设计一种文件格式,所以我想正确地做。既然是二进制格式,该文件的第一个字节(或字节)应形成有效的文本字符(就像在PNG文件头1)。这使得无法识别格式的工具通过查看前几个字节仍然可以看到它不是文本文件。

上面的任何代码点0x7F都是无效的US-ASCII,因此很容易。但是对于Unicode则完全不同。除了有效的Unicode字符有私用字符noncharacters哨兵,我在发现Unicode的私用字符,Noncharacters和哨兵常见问题解答

我可以在文件开头使用什么样的前哨字节序列,从而导致无效的US-ASCII,UTF-8,UTF-16LE和UTF-16BE?

  • 显然,第一个字节不能具有低于0x80此值的值,因为该值将是有效的US-ASCII(控制)字符,因此0x00无法使用。
  • 另外,由于专用字符是有效的Unicode字符,所以我也不能使用这些代码点。
  • 由于它必须同时使用Little-endian和Big-endian UTF-16,因此也不能使用非字符0xFFFE因为其反向0xFEFF是有效的Unicode字符。
  • 上面提到的常见问题解答建议不要使用任何非字符,因为这仍然会导致有效的Unicode序列,因此,类似的东西0xFFFF也无法使用。

让我使用的面向未来的前哨值是什么?


1)PNG格式的第一个字节为非ASCII 0x89值,其后为字符串PNG。读取PNG的前几个字节的工具可能会确定它是二进制文件,因为它无法解释0x89。另一方面,GIF文件直接以有效且可读的ASCII字符串GIF开头,后跟另外三个有效ASCII字符。对于GIF,工具可能会确定它是可读的文本文件。这是错误的,并且以非文本字节序列启动文件的想法来自Andy McFadden的“ 设计文件格式”


3
Since it is a binary format, the first bytes of the file should not form valid textual characters-您应该查看魔术文件(在许多Unix系统上为/ usr / share / magic或/ etc / magic),该文件显示了此应用程序如何识别文件类型。一个PNG文件开始于\x89PNG\x0d\0a\x1a\x0a-请注意其中的“ PNG”,这是一个原始字符串。序列\x89等是不可打印的字节。

@MichaelT是的,由于PNG是二进制格式,因此第一个字节不能形成有效的文本字符。我正是这个意思。我看不到你的意思吗?
Daniel AA Pelsmaeker 2013年

7
那是一个例子。.gif开头为GIF8。SGI movi文件以开头MOVI。一种样式的zip存档文件开始于ZZ,另一种流行的pkzip格式的开始于PK。第一个字节为无效文本字符的约束似乎与在野外发现的不匹配。我很好奇为什么这是必要条件。

3
您真的关心其他程序在看到未知文件时的行为吗?对我来说,签名序列(如PNG文件)比哨兵序列有用得多-当内容通过简单的流协议发送时,接收者可以立即决定如何处理以下字节。一旦每个人都开始使用阿曼前哨序列来识别自己的格式,它就会紧随其后。
Codism 2013年

2
@Virtlink,我并不特别在意文件格式中使用的字节。但是您断言使用ascii字符是“错误的” ...但是我在这里还没有看到任何支持该主张的内容,并且有大量的经验表明它确实无关紧要(即,无数的文件)几十年来一直使用ASCII字符没有问题的格式)
GrandmasterB

Answers:


16

0xDC 0xDC

  • 显然无效的UTF-8和ASCII
  • 不管UTF-16的字节序如何,未配对的线索都​​将处于领先位置。没有比这更多的无效UTF-16了。

但是ISO-8859-1完全合理,并且在使用8位编码的任何其他字符集中也可能合理。
parsifal 2013年

4
+1 OP不需要ISO 8859-1,而只是要求US-ASCII和UTF- *。
Ross Patterson

@RossPatterson-是的,但我怀疑这主要是因为OP并未真正考虑问题。没有任何统计数据可支持我,我敢打赌,随机的“是此文本”算法比UTF-16更倾向于使用ISO-8859-1,这仅仅是因为存在大量的8位世界上的文字。
parsifal 2013年

3
@parsifal任何二进制文件都是有效的ISO-8859-1,因此不必仅仅因为无法生成无效的ISO-8859-1而就不必考虑它。
Esailija

1
@parsifal是真的,如果这是您可以使用的要求,则可以使用0x00op,但op并不想那样。
Esailija 2013年

5
  • 在UTF-8中,字节C0,C1和F5-FF是非法的。第一个字节必须是ASCII或C2-F4范围内的字节,其他任何起始字节都不是有效的UTF-8。

  • 在UTF-16中,文件通常以字节顺序标记(U + FEFF)开头,否则应用程序必须猜测字节顺序。D800-DBFF范围内的代码点是代理对的前导字节,DC00-DFFF是代理对的尾随字节。

因此,我将使用字节combo F5DC。这两个值是:

  • 不是ASCII
  • 无效的UTF-8
  • 可以解释为代理对中的UTF-16尾部字节(不合法),也可以是代码点U + F5DC,这是私人使用的字符,但只能由即使没有BOM也会顽固地尝试将其解释为UTF-16的应用程序。

如果你需要更多的选择,F5DD通过对F5DF所有具有相同的3个属性,因为这样做F6DC- F6DFF7DC- F7DFF8DC- F8DF,一共有16个不同的字节连击的取货地点。


因此,按照Esailija的建议使用U + DCDC,0xDC将是有效的UTF-8吗?
Daniel AA Pelsmaeker 2013年

2
@Virtlink 0xDC是2字节序列的UTF-8前导字节。它必须后跟一个10xxxxxx连续字节才能生效。0xDC不是有效的连续字节,因此0xDC 0xDC无效的UTF-8。
Esailija

@Virtlink:否,因为第二个字节无效,所以它必须在80- 范围内BF
马丁·彼得

2

如果您试图使用不可打印的字符来表示“非文本”,那么您将很难击败0x89:

  • 它不在US-ASCII范围内
  • 在ISO-8859-1中,它是不可打印的字符(“带有合理性的字符制表符”)。同样,我相信Shift-JIS仍然很常用。但是,其他8位编码也可以将其视为有效字符。
  • 在UTF-8中,对于多字节序列,它的第一个字节无效(高位为10,保留给多字节序列的字符2..N)。

通常,当您形成幻数时,“非文本”是次要点。我必须查找参考,但是一种标准的图形格式(我认为是TIFF)从其幻数中可以得到六种不同的有用信息。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.