执行 String.Encoding.utf 16 和 String.Encoding。 utf16 BigEndian 意思是一样的,即 UTF16 BigEndian?
Do String.Encoding.utf16 and String.Encoding. utf16BigEndian mean the same thing i.e UTF16BigEndian?
我有一个用 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。在 big endian 中,它将是 0xfe,0xff。
使用 .utf16
您可以读取正确的 UTF-16 数据(我的意思是拥有正确的 BOM),即使在字节序不匹配的平台上也是如此。
输入 print(data as NSData)
并检查 data
的前两个字节。我猜它包含 0xfe、0xff(大端 BOM。)
看来我的猜测是错误的,当找不到 BOM 时,Apple 基金会的 .utf16
更喜欢 Big Endian 而不是平台的本机字节序。 (也许有一些历史原因,因为 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 字符组成时,这种预测可能 wrong.This 适用,如果你正在预测字节顺序。
但通常您应该使用 unicode 标准,该标准规定如果找不到 BOM,您应该将字节视为大端。
我有一个用 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。在 big endian 中,它将是 0xfe,0xff。
使用 .utf16
您可以读取正确的 UTF-16 数据(我的意思是拥有正确的 BOM),即使在字节序不匹配的平台上也是如此。
输入 print(data as NSData)
并检查 data
的前两个字节。我猜它包含 0xfe、0xff(大端 BOM。)
看来我的猜测是错误的,当找不到 BOM 时,Apple 基金会的 .utf16
更喜欢 Big Endian 而不是平台的本机字节序。 (也许有一些历史原因,因为 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 字符组成时,这种预测可能 wrong.This 适用,如果你正在预测字节顺序。
但通常您应该使用 unicode 标准,该标准规定如果找不到 BOM,您应该将字节视为大端。