ios - 执行 String.Encoding.utf16 和 String.Encoding。 utf16BigEndian 意味着同样的事情即 UTF16BigEndian?

标签 ios swift xcode foundation

我有一个用 utf16 big endian 编码的字符串的字节。这些字节是我从我的同事与我共享的文件中读取的,他确认该字符串是 utf16 bigendian。

出于演示目的,我读取了文件来解释字符串。代码如下:

let bundle = Bundle(for: ViewController.self)
guard let url = bundle.url(forResource: "TestBingEndian", withExtension: "txt") else { return }
let data = try! Data(contentsOf: url)
        print(data)

let bigEndianString = String(bytes: data, encoding: .utf16BigEndian)
print("bigEndianString: \(bigEndianString!)")

let littleEndian = String(bytes: data, encoding: .utf16LittleEndian)
print("littleEndian: \(littleEndian!)")

let endiannessNotSpecifiedString = String(bytes: data, encoding: .utf16)
print("endiannessNotSpecifiedString: \(endiannessNotSpecifiedString!)")

bigEndianString 的输出符合预期。

littleEndian 的输出没有用,因为它对我来说是垃圾。

endiannessNotSpecifiedString 的输出也符合预期并与 bigEndianString 匹配。

所以我的问题是,.utf16 和 .utf16BigEndian 是一回事吗?

PS:我的机器是小端。我认为 .utf16 应该是我的机器字节顺序。但根据我的测试结果是双序排列。

最佳答案

所以我的问题是,.utf16 和 .utf16BigEndian 是一回事吗?

没有。正确的 UTF-16 需要在文件顶部包含 BOM。

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代表小端的BOM。在大端,它将是 0xfe,0xff。

使用 .utf16,即使在端序不匹配的平台上,您也可以读取正确的 UTF-16 数据(我的意思是拥有正确的 BOM)。

输入print(data as NSData) 并检查data 的前两个字节。我猜它包含 0xfe、0xff(大端 BOM。)


似乎我的猜测是错误的,当找不到 BOM 时,Apple Foundation 中的 .utf16 更喜欢 Big Endian 而不是平台的 native 字节序。 (也许有一些历史原因,因为 Apple 曾经使用 Big Endian 平台,68k 或 Power-PC。正如 Martin R 的评论,它是在 The Unicode Standard 中定义的。看来我需要更新我的知识.)

但是当您知道您的数据不包含 BOM 时,您最好指定 .utf16BigEndian,而在 Big Endian 中,.utf16 用于包含正确 BOM 的数据。

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 字符组成时,这种预测可能是错误的。如果你预测字节顺序,这适用.

但通常您应该使用 unicode 标准,该标准规定如果找不到 BOM,您应该将字节视为大端。

关于ios - 执行 String.Encoding.utf16 和 String.Encoding。 utf16BigEndian 意味着同样的事情即 UTF16BigEndian?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55566909/

相关文章:

iphone - 在多个类中使用 FMOD (iOS)

ios - 同一部分内单元格之间的可变空间

swift - 无法等待 MKDirections.calculate 的结果,取而代之的是 nil

swift - 需要解释在自定义类型上声明惰性属性

ios - 如何升级到 Xcode 4.5

iphone - 从不兼容类型 'AppDelegate *' 分配给 'id<UIApplicationDelegate>'

ios - Xcode 9 错误 : "iPhone has denied the launch request"

ios - Swift (iOS),等待所有图片下载完成再返回

xcode - 从 Swift Playground 中的 Completion Handler 打印到控制台

ios - 如何向 UINavigationBar 添加按钮?