4.14. 字符串的 Unicode 表示形式

当一个 Unicode 字符串被写进文本文件或者其他储存时,字符串中的 Unicode 标量会用 Unicode 定义的几种 编码格式(encoding forms)编码。每一个字符串中的小块编码都被称 代码单元(code units)。这些包括 UTF-8 编码格式(编码字符串为 8 位的代码单元), UTF-16 编码格式(编码字符串位 16 位的代码单元),以及 UTF-32 编码格式(编码字符串32位的代码单元)。

Swift 提供了几种不同的方式来访问字符串的 Unicode 表示形式。你可以利用 for-in 来对字符串进行遍历,从而以 Unicode 可扩展的字符群集的方式访问每一个 Character 值。该过程在 4.6. 使用字符 中进行了描述。

另外,能够以其他三种 Unicode 兼容的方式访问[字符串](/tag/59e.html)的值:

  • UTF-8 代码单元集合(利用字符串的 utf8 属性进行访问)
  • UTF-16 代码单元集合(利用字符串的 utf16 属性进行访问)
  • 21 位的 Unicode 标量值集合,也就是字符串的 UTF-32 编码格式(利用字符串的 unicodeScalars 属性进行访问)

下面由 D,o,g,(DOUBLE EXCLAMATION MARK, Unicode 标量 U+203C)和 🐶(DOG FACE,Unicode 标量为 U+1F436)组成的字符串中的每一个字符代表着一种不同的表示:let dogString = "Dog‼🐶"

UTF-8 表示

你可以通过遍历 Stringutf8 属性来访问它的 UTF-8 表示。其为 String.UTF8View 类型的属性,UTF8View 是无符号 8 位(UInt8)值的集合,每一个 UInt8 值都是一个字符的 UTF-8 表示:

Character DU+0044 oU+006F gU+0067 ‼U+203C 🐶U+1F436
UTF-8 Code Unit 68 111 103 226 128 188 240 159 144 182
Position 0 1 2 3 4 5 6 7 8 9
for codeUnit in dogString.utf8 {
    print("\(codeUnit) ", terminator: "")
}
print("")
// 68 111 103 226 128 188 240 159 144 182

上面的例子中,前三个 10 进制 codeUnit 值(68111103)代表了字符 Dog,它们的 UTF-8 表示与 ASCII 表示相同。接下来的三个 10 进制 codeUnit 值(226128188)是 DOUBLE EXCLAMATION MARK 的3字节 UTF-8 表示。最后的四个 codeUnit 值(240159144182)是 DOG FACE 的4字节 UTF-8 表示。

UTF-16 表示

你可以通过遍历 Stringutf16 属性来访问它的 UTF-16 表示。其为 String.UTF16View 类型的属性,UTF16View 是无符号16位(UInt16)值的集合,每一个 UInt16 都是一个字符的 UTF-16 表示:

Character DU+0044 oU+006F gU+0067 ‼U+203C 🐶U+1F436
UTF-16 Code Unit 68 111 103 8252 55357 56374
Position 0 1 2 3 4 5
for codeUnit in dogString.utf16 {
    print("\(codeUnit) ", terminator: "")
}
print("")
// 68 111 103 8252 55357 56374

同样,前三个 codeUnit 值(68111103)代表了字符 Dog,它们的 UTF-16 代码单元和 UTF-8 完全相同(因为这些 Unicode 标量表示 ASCII 字符)。

第四个 codeUnit 值(8252)是一个等于十六进制 203C 的的十进制值。这个代表了 DOUBLE EXCLAMATION MARK 字符的 Unicode 标量值 U+203C。这个字符在 UTF-16 中可以用一个代码单元表示。

第五和第六个 codeUnit 值(5535756374)是 DOG FACE 字符的 UTF-16 表示。第一个值为 U+D83D(十进制值为 55357),第二个值为 U+DC36(十进制值为 56374)。

Unicode 标量表示

你可以通过遍历 String 值的 unicodeScalars 属性来访问它的 Unicode 标量表示。其为 UnicodeScalarView 类型的属性,UnicodeScalarViewUnicodeScalar 类型的值的集合。

每一个 UnicodeScalar 拥有一个 value 属性,可以返回对应的 21 位数值,用 UInt32 来表示:

Character DU+0044 oU+006F gU+0067 ‼U+203C 🐶U+1F436
Unicode Scalar Code Unit 68 111 103 8252 128054
Position 0 1 2 3 4
for scalar in dogString.unicodeScalars {
    print("\(scalar.value) ", terminator: "")
}
print("")
// 68 111 103 8252 128054

前三个 UnicodeScalar 值(68111103)的 value 属性仍然代表字符 Dog

第四个 codeUnit 值(8252)仍然是一个等于十六进制 203C 的十进制值。这个代表了 DOUBLE EXCLAMATION MARK 字符的 Unicode 标量 U+203C

第五个 UnicodeScalar 值的 value 属性,128054,是一个十六进制 1F436 的十进制表示。其等同于 DOG FACE 的 Unicode 标量 U+1F436

作为查询它们的 value 属性的一种替代方法,每个 UnicodeScalar 值也可以用来构建一个新的 String 值,比如在字符串插值中使用:

for scalar in dogString.unicodeScalars {
    print("\(scalar) ")
}
// D
// o
// g
// ‼
// 🐶