Итак, мой вопрос: .utf16 и .utf16BigEndian - это одно и то же?
Нет. Правильный UTF-16 должен содержать спецификацию в верхней части файла.
let str = "Hello, World!"
let dataUTF16 = str.data(using: .utf16)!
print(dataUTF16 as NSData)
let dataUTF16BE = str.data(using: .utf16BigEndian)!
print(dataUTF16BE as NSData)
let dataUTF16LE = str.data(using: .utf16LittleEndian)!
print(dataUTF16LE as NSData)
Выход:
<fffe4800 65006c00 6c006f00 2c002000 57006f00 72006c00 64002100>
<00480065 006c006c 006f002c 00200057 006f0072 006c0064 0021>
<48006500 6c006c00 6f002c00 20005700 6f007200 6c006400 2100>
0xff, 0xfe представляет спецификацию с прямым порядком байтов. В старшем порядке это будет 0xfe, 0xff.
С помощью .utf16
вы можете читать правильные данные UTF-16 (я имею в виду наличие правильной спецификации), даже в несовпадающей платформе с прямым порядком байтов.
Положите print(data as NSData)
и проверьте первые два байта вашего data
. Я предполагаю, что он содержит 0xfe, 0xff (спецификация в старшем порядке).
Кажется, мое предположение было неверным, и .utf16
в Apple Foundation предпочитает Big Endian, а не собственный порядковый номер платформы, когда спецификация не найдена. ( Возможно, есть какая-то историческая причина, так как Apple использовала платформы Big Endian, 68k или Power-PC. Как и в комментарии Мартина Р., это определено в стандарте Unicode. Кажется, мне нужно обновить свои знания. )
Но вам лучше указать .utf16BigEndian
, если вы знаете, что ваши данные не содержат спецификации, а в Big Endian, .utf16
для данных, содержащих правильную спецификацию.
let str = "Hello, World!"
let dataUTF16 = str.data(using: .utf16)!
print(dataUTF16 as NSData)
let strUTF16asUTF16 = String(data: dataUTF16, encoding: .utf16)
debugPrint(strUTF16asUTF16) //->Optional("Hello, World!")
let strUTF16asUTF16BE = String(data: dataUTF16, encoding: .utf16BigEndian)
debugPrint(strUTF16asUTF16BE) //->Optional("䠀攀氀氀漀Ⰰ 圀漀爀氀搀℀")
let strUTF16asUTF16LE = String(data: dataUTF16, encoding: .utf16LittleEndian)
debugPrint(strUTF16asUTF16LE) //->Optional("Hello, World!")
Когда почти все символы состоят из символов ASCII, сработает какое-то предсказание порядка байтов, но когда большинство из них состоят из символов не-ASCII, такие прогнозы могут быть неверными. Это применимо, если вы прогнозируете порядок байтов .
Но, как правило, вы должны использовать стандарт Юникода, который гласит, что если BOM не найден, вы должны обращаться с байтами как с прямым порядком байтов.