我怎样才能得到一个字符的Unicode代码点?
我怎样才能提取一个给定的Character
的Unicode代码点(S)没有先把它转换为一个String
? 我知道我可以使用以下内容:
let ch: Character = "A" let s = String(ch).unicodeScalars s[s.startIndex].value // returns 65
但似乎应该有一个更直接的方式来完成这个使用Swift的标准库。 “语言指南”部分中的“使用字符”和“Unicode”仅讨论迭代String
中的String
,而不直接与Character
s一起工作。
从我可以在文档中收集的内容,他们希望您从String
获取Character
值,因为它提供了上下文。 这个Character
是用UTF8,UTF16还是21位代码点(标量)编码的?
如果你看看在Swift框架中如何定义一个Character
,它实际上是一个enum
值。 这可能是由于来自String.utf8
, String.utf16
和String.unicodeScalars
的各种表示。
看起来他们不希望你使用Character
值而是Strings
而你作为程序员决定如何从String
本身获取这些值,从而允许保留编码。
也就是说,如果您需要以简洁的方式获取代码点,我会推荐一个像这样的扩展:
extension Character { func unicodeScalarCodePoint() -> UInt32 { let characterString = String(self) let scalars = characterString.unicodeScalars return scalars[scalars.startIndex].value } }
那么你可以这样使用它:
let char : Character = "A" char.unicodeScalarCodePoint()
总之,string和字符编码是一个棘手的事情,当你考虑到所有的可能性。 为了让每一个可能性代表,他们去了这个计划。
还记得这是一个1.0版本,我相信他们很快就会扩展Swift的语法糖。
我认为对Unicode有一些误解。 Unicode本身不是一种编码,它不会将任何字形集群(或“人物”从人类阅读的尊重)转换成任何types的二进制序列。 Unicode只是一个收集地球上所有语言(非官方还包括克林贡语)使用的所有字形集群的大桌子。 这些字形集群是由代码点(一个21位的数字在迅速,看起来像U + D800)组织和索引。 通过使用代码点,您可以在大Unicode表中find您要查找的字符
同时,称为UTF8,UTF16,UTF32的协议实际上是编码。 是的,有多种方法可以将Unicode字符编码为二进制序列。 使用哪种协议取决于您正在工作的项目,但大多数网页是由UTF-8编码的(您现在可以实际检查它)。
概念1: Unicode点被称为Swift中的Unicode标量
Unicode标量是从U + 0000到U + D7FF(含)或U + E000到U + 10FFFF(含)的任何Unicode代码点。 Unicode标量不包括Unicode代理对代码点,它是U + D800到U + DFFF(含)范围内的代码点。
概念2: 代码单元是编码的抽象表示。
考虑下面的代码片段
let theCat = "Cat!🐱" for char in theCat.utf8 { print("\(char) ", terminator: "") //Code Unit of each grapheme cluster for the UFT8 encoding } print("") for char in theCat.utf8 { print("\(String(char, radix: 2)) ", terminator: "") //Encoding of each grapheme cluster for the UTF8 encoding } print("") for char in theCat.utf16 { print("\(char) ", terminator: "") //Code Unit of each grapheme cluster for the UFT-16 encoding } print("") for char in theCat.utf16 { print("\(String(char, radix: 2)) ", terminator: "") //Encoding of each grapheme cluster for the UTF-16 encoding } print("") for char in theCat.unicodeScalars { print("\(char.value) ", terminator: "") //Code Unit of each grapheme cluster for the UFT-32 encoding } print("") for char in theCat.unicodeScalars { print("\(String(char.value, radix: 2)) ", terminator: "") //Encoding of each grapheme cluster for the UTF-32 encoding }
抽象表示的意思是 :代码单元是由base-10编码(十进制数)写的,它等于base-2编码(二进制序列)。 编码是为机器编写的,Code Unit更适合人类,读取比二进制序列容易。
概念3:一个字符可能有不同的Unicode点。 这取决于字符是如何被字形集群收缩的(这就是为什么我从开始时的人类阅读方面说“字符” )
考虑下面的代码片段
let precomposed: String = "\u{D55C}" let decomposed: String = "\u{1112}\u{1161}\u{11AB}" print(precomposed.characters.count) // print "1" print(decomposed.characters.count) // print "1" => Character != grapheme cluster print(precomposed) //print "한" print(decomposed) //print "한"
precomposed
decomposed
和decomposed
的字符在视觉上和语言上是相同的,但是如果它们使用相同的编码协议进行编码,则它们具有不同的Unicode点和不同的编码单元(参见下面的例子)
for preCha in precomposed.utf16 { print("\(preCha) ", terminator: "") //print 55357 56374 128054 54620 } print("") for deCha in decomposed.utf16 { print("\(deCha) ", terminator: "") //print 4370 4449 4523 }
额外的例子
var word = "cafe" print("the number of characters in \(word) is \(word.characters.count)") word += "\u{301}" print("the number of characters in \(word) is \(word.characters.count)")
摘要 : 代码点 ,也就是Unicode中字符的位置索引,与UTF-8,UTF-16和UTF-32编码scheme无关。
进一步阅读 :
http://www.joelonsoftware.com/articles/Unicode.html
http://kunststube.net/encoding/
https://www.mikeash.com/pyblog/friday-qa-2015-11-06-why-is-swifts-string-api-so-hard.html
我同意你的看法,应该有一种直接从angular色获取代码的方法。 但是我能提供的只是一个简写:
let ch: Character = "A" for code in String(ch).utf8 { println(code) }
我认为问题是, Character
不代表一个Unicode代码点。 它代表一个“Unicode字形集群”,它可以由多个代码点组成。
相反, UnicodeScalar
表示一个Unicode代码点。
你有没有尝试过:
import Foundation let characterString: String = "abc" var numbers: [Int] = Array<Int>() for character in characterString.utf8 { let stringSegment: String = "\(character)" let anInt: Int = stringSegment.toInt()! numbers.append(anInt) } numbers
输出:
[97,98,99]
它也可能只是string中的一个字符。