【发布时间】:2014-08-23 21:31:15
【问题描述】:
我们知道 String.utf16 提供代码单元或 String.unicodeScalars 提供标量。
如果我们通过删除一些元素等来操作 codeunits 和 unicodeScales。有没有办法重新构造结果字符串?
【问题讨论】:
我们知道 String.utf16 提供代码单元或 String.unicodeScalars 提供标量。
如果我们通过删除一些元素等来操作 codeunits 和 unicodeScales。有没有办法重新构造结果字符串?
【问题讨论】:
Swift 2.1 更新:
您可以从 UTF-16 字符数组创建String
与
public init(utf16CodeUnits: UnsafePointer<unichar>, count: Int)
初始化程序。示例:
let str = "H€llo ?"
// String to UTF16 array:
let utf16array = Array(str.utf16)
print(utf16array)
// Output: [72, 8364, 108, 108, 111, 32, 55357, 56836]
// UTF16 array to string:
let str2 = String(utf16CodeUnits: utf16array, count: utf16array.count)
print(str2)
// H€llo ?
上一个答案:
没有任何“内置”(据我所知),但您可以使用 UTF16 结构
它提供了一个decode() 方法:
extension String {
init?(utf16chars:[UInt16]) {
var str = ""
var generator = utf16chars.generate()
var utf16 : UTF16 = UTF16()
var done = false
while !done {
let r = utf16.decode(&generator)
switch (r) {
case .EmptyInput:
done = true
case let .Result(val):
str.append(Character(val))
case .Error:
return nil
}
}
self = str
}
}
例子:
let str = "H€llo ?"
// String to UTF16 array:
let utf16array = Array(str.utf16)
print(utf16array)
// Output: [72, 8364, 108, 108, 111, 32, 55357, 56836]
// UTF16 array to string:
if let str2 = String(utf16chars: utf16array) {
print(str2)
// Output: H€llo ?
}
稍微通用,你可以定义一个创建字符串的方法 使用给定的编解码器从代码点数组(或任何序列)中:
extension String {
init?<S : SequenceType, C : UnicodeCodecType where S.Generator.Element == C.CodeUnit>
(codeUnits : S, var codec : C) {
var str = ""
var generator = codeUnits.generate()
var done = false
while !done {
let r = codec.decode(&generator)
switch (r) {
case .EmptyInput:
done = true
case let .Result(val):
str.append(Character(val))
case .Error:
return nil
}
}
self = str
}
}
然后从 UTF16 转换为
if let str2a = String(codeUnits: utf16array, codec: UTF16()) {
print(str2a)
}
这是另一种可能的解决方案。虽然之前的方法是“纯 Swift”,但这个使用 Foundation 框架和自动
NSString 和 Swift String 之间的桥接:
extension String {
init?(utf16chars:[UInt16]) {
let data = NSData(bytes: utf16chars, length: utf16chars.count * sizeof(UInt16))
if let ns = NSString(data: data, encoding: NSUTF16LittleEndianStringEncoding) {
self = ns as String
} else {
return nil
}
}
}
【讨论】:
while !done 部分是我发现标记中断在 Swift 中有用的少数几次之一,即end: while true … case .EmptyInput: break end
在这里。
extension String {
static func fromUTF16Chars(utf16s:UInt16[]) -> String {
var str = ""
for var i = 0; i < utf16s.count; i++ {
let hi = Int(utf16s[i])
switch hi {
case 0xD800...0xDBFF:
let lo = Int(utf16s[++i])
let us = 0x10000
+ (hi - 0xD800)*0x400 + (lo - 0xDC00)
str += Character(UnicodeScalar(us))
default:
str += Character(UnicodeScalar(hi))
}
}
return str
}
}
let str = "aαあ?aαあ?"
var utf16cs = UInt16[]()
for utf16c in str.utf16 {
utf16cs += utf16c
}
let str2 = String.fromUTF16Chars(utf16cs)
assert(str2 == str)
println(str2)
【讨论】: