Значение Юникода, которое я могу использовать?

14

Я разрабатываю формат файла и хочу сделать все правильно. Поскольку это двоичный формат, самый первый байт (или байты) файла не должен образовывать допустимые текстовые символы (как в заголовке файла PNG 1 ). Это позволяет инструментам, которые не распознают формат, по-прежнему видеть, что это не текстовый файл, просматривая первые несколько байтов.

Любой код, указанный выше, 0x7Fявляется недействительным US-ASCII, так что это легко. Но для Unicode это совсем другая история. Помимо допустимых символов Юникода, есть частные символы , нехарактеры и стражи , как я нашел в FAQ по частным персонажам , нехарактерам и часовым .

Какой будет последовательность байтов, которую я могу использовать в начале файла, что приведет к неправильным US-ASCII, UTF-8, UTF-16LE и UTF-16BE?

  • Очевидно, что первый байт не может иметь значения ниже, 0x80поскольку это будет действительный символ US-ASCII (управляющий), поэтому 0x00его нельзя использовать.
  • Кроме того, поскольку символы частного использования являются допустимыми символами Unicode, я не могу использовать эти кодовые точки.
  • Так как он должен работать как с UTF-16 с прямым порядком байтов, так и с прямым порядком байтов, такой символ , который не является символом , 0xFFFEтакже невозможен, так как его обратный 0xFEFFсимвол является допустимым символом Unicode.
  • Вышеупомянутые часто задаваемые вопросы предлагают не использовать какой-либо из нехарактерных символов, так как это все равно приведет к правильной последовательности Юникода, поэтому что-то вроде этого 0xFFFFтакже не видно .

Каковы будут сохраняемые для будущего значения дозорных, которые я оставлю для использования?


1 ) Формат PNG имеет в качестве самого первого байта значение не ASCII 0x89, за которым следует строка PNG. Инструмент, который считывает первые несколько байтов PNG, может определить, что это двоичный файл, так как он не может интерпретировать 0x89. Файл GIF, с другой стороны, начинается непосредственно с допустимой и читаемой строки ASCII, GIFза которой следуют еще три действительных символа ASCII. Для GIF инструмент может определить, что это читаемый текстовый файл. Это неверно, и идея начать файл с нетекстурной байтовой последовательности пришла от Энди Макфаддена « Разработка форматов файлов ».

Даниэль А.А. Пельсмакер
источник
3
Since it is a binary format, the first bytes of the file should not form valid textual characters- Вы должны посмотреть на волшебный файл (/ usr / share / magic или / etc / magic на многих системах Unix), который показывает, как это приложение идентифицирует типы файлов. Файл PNG начинается с \x89PNG\x0d\0a\x1a\x0a- обратите внимание на «PNG», это необработанная строка. Последовательности \x89и т.п. являются непечатными байтами.
@MichaelT Да, поскольку PNG является двоичным форматом, первый байт не образует допустимого текстового символа. Это то, что я имел в виду. Я не вижу твоей точки зрения?
Даниэль А.А. Пельсмакер
7
Это был пример. .Gif начинается с GIF8. Файл SGI MOVI начинается с MOVI. Один стиль файла архива zip начинается с ZZболее популярного формата pkzip PK. Ограничение на то, что первый байт будет недопустимым текстовым символом, похоже, не соответствует тому, что найдено в wild. Мне любопытно, почему это требование.
3
Вы действительно заботитесь о том, как ведут себя другие программы, когда они видят неизвестный файл? Для меня последовательность подписи (например, файлы PNG) гораздо более полезна, чем последовательность дозорного: когда содержимое отправляется по простому потоковому протоколу, получатель может сразу решить, как обрабатывать следующие байты. Последовательность Omani-Sentinel почти не имеет последовательности, как только каждый начинает использовать ее для идентификации своего собственного формата.
Кодизм
2
@Virtlink, мне не особо важно, какие байты вы используете в своем формате файла. Но вы сделали утверждение, что «неправильно» использовать символы ascii ... но я не видел здесь ничего, что поддерживало бы это утверждение, и есть много эмпирического опыта, который показывает, что это действительно не имеет значения (то есть бесчисленное количество файлов форматы, в которых десятилетиями без проблем использовались символы ASCII)
GrandmasterB

Ответы:

16

0xDC 0xDC

  • Очевидно, недействительные UTF-8 и ASCII
  • Непарный суррогат следа в лидирующей позиции независимо от порядка байтов в UTF-16. Он не получает больше недействительных UTF-16, чем это.
Esailija
источник
Но вполне разумный ISO-8859-1 и, вероятно, разумный в любом другом наборе символов, который использует 8-битное кодирование.
Парсифаль
4
+1 OP не запрашивал ISO 8859-1, только US-ASCII и UTF- *.
Росс Паттерсон
@RossPatterson - правда, но я подозреваю, что это в основном потому, что ОП на самом деле не продумал проблему. Без какой-либо статистики, чтобы поддержать меня, я готов поспорить, что случайный алгоритм «это текст» с большей вероятностью отдает предпочтение ISO-8859-1, чем UTF-16, просто потому, что существует огромное количество 8-битных текст в мире.
Парсифаль
3
@parsifal Любой двоичный файл является допустимым ISO-8859-1, поэтому его не нужно рассматривать просто потому, что невозможно сделать недействительным ISO-8859-1.
Esailija
1
@parsifal true, и если это было требованием, которое вы могли бы просто использовать 0x00или что-то еще, но операционист не хотел этого.
Esailija
5
  • В UTF-8 байты C0, C1 и F5 - FF недопустимы. Первый байт должен быть либо ASCII, либо байтом в диапазоне C2-F4, любой другой начальный байт не является допустимым UTF-8.

  • В UTF-16 файл обычно начинается с метки порядка байтов (U + FEFF), в противном случае приложения должны угадывать порядок байтов. Кодовые точки в диапазоне D800-DBFF являются ведущими байтами для суррогатной пары, а DC00-DFFF являются конечными байтами для суррогатной пары.

Таким образом, я бы использовал байтовую комбинацию F5DC. Эти два значения:

  • Не ASCII
  • Не действует UTF-8
  • Либо интерпретировать как UTF-16 заднего байта суррогатной пары (не юридического), или элемент кода U + F5DC, которая является частное использование символов, но только в приложениях , которые упорно пытаются интерпретировать это как UTF-16 даже без BOM ,

Если вам нужно больше вариантов, F5DDчерез , чтобы F5DFвсе они имеют те же 3 свойства, как и у F6DC- F6DF, F7DC- F7DFи F8DC- F8DF, в общей сложности 16 различных байт комбо , чтобы выбрать из.

Мартейн Питерс
источник
Итак, по предложению Эсайлии использовать U + DCDC, 0xDCбудет ли действительным UTF-8?
Даниэль А.А. Пельсмакер,
2
@Virtlink 0xDC- ведущий байт UTF-8 для двухбайтовой последовательности. За ним должен следовать 10xxxxxxбайт продолжения, чтобы он был действительным. 0xDCне является действительным байтом продолжения, поэтому 0xDC 0xDCне является допустимым UTF-8.
Esailija
@Virtlink: Нет, поскольку второй байт недействителен, он должен быть в диапазоне 80- BF.
Мартейн Питерс
2

Если вы пытаетесь использовать непечатаемый символ для обозначения «не текст», то вам будет трудно победить 0x89:

  • Это вне диапазона США-ASCII
  • В ISO-8859-1 это непечатаемый символ («ТАБЛИЦА ХАРАКТЕРОВ С ОБОСНОВАНИЕМ»). Аналогично с Shift-JIS, который, я считаю, все еще широко используется. Однако другие 8-битные кодировки могут воспринимать это как допустимый символ.
  • В UTF-8 это недопустимый первый байт для многобайтовой последовательности (старшие биты равны 10, которые зарезервированы для символов 2..N многобайтовой последовательности)

Как правило, когда вы формируете магические числа, «нетекст» является второстепенной точкой. Мне придется поискать ссылку, но один из стандартных графических форматов (я думаю, TIFF) содержит что-то вроде шести разных частей полезной информации из своего магического числа.

Парсифаль
источник