【问题标题】:Is there a way to create a String from utf16 array in swift?有没有办法快速从 utf16 数组创建字符串?
【发布时间】:2014-08-23 21:31:15
【问题描述】:

我们知道 String.utf16 提供代码单元或 String.unicodeScalars 提供标量。

如果我们通过删除一些元素等来操作 codeunits 和 unicodeScales。有没有办法重新构造结果字符串?

【问题讨论】:

    标签: string swift bytearray


    【解决方案1】:

    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
    【解决方案2】:

    在这里。

    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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-30
      • 1970-01-01
      • 2017-08-17
      • 2011-04-28
      • 2021-10-25
      • 1970-01-01
      • 2017-01-23
      • 1970-01-01
      相关资源
      最近更新 更多