【问题标题】:Convert UInt32 (UTF-32) to String in Swift在 Swift 中将 UInt32 (UTF-32) 转换为字符串
【发布时间】:2015-10-03 22:36:23
【问题描述】:

我有一个 UInt32 值数组。我想将此数组转换为String

这不起作用:

let myUInt32Array: [UInt32] = [72, 101, 108, 108, 111, 128049]
let myString = String(myUInt32Array) // error
let myString = String(stringInterpolationSegment: myUInt32Array) // [72, 101, 108, 108, 111, 128049] (not what I want)

这些 SO 帖子显示 UTF8UTF16

【问题讨论】:

    标签: ios string swift uint32


    【解决方案1】:

    UnicodeScalarUInt32 的类型别名。因此,将您的 UInt32 值转换为 UnicodeScalar,然后将它们附加到 String

    let myUInt32Array: [UInt32] = [72, 101, 108, 108, 111, 128049]
    
    var myString: String = ""
    
    for value in myUInt32Array {
        if let scalar = UnicodeScalar(value) {
            myString.append(Character(scalar))
        }
    }
    
    print(myString) // Hello?
    

    【讨论】:

    • @jvarela,已更新。感谢您的通知。除了首先转换为Character,还必须检查UInt32 值是否为nil
    【解决方案2】:

    (答案已针对 Swift 4 及更高版本更新。)

    使用 Swift 类型 DataString 可以这样做

    let myUInt32Array: [UInt32] = [72, 101, 108, 108, 111, 128049, 127465, 127466]
    let data = Data(bytes: myUInt32Array, count: myUInt32Array.count * MemoryLayout<UInt32>.stride)
    let myString = String(data: data, encoding: .utf32LittleEndian)!
    print(myString) // Hello???
    

    这里使用强制解包,因为从 UTF-32 转换 指向字符串的代码点不能失败。

    为方便起见,您可以定义一个String 扩展名

    extension String {
        init(utf32chars:[UInt32]) {
            let data = Data(bytes: utf32chars, count: utf32chars.count * MemoryLayout<UInt32>.stride)
            self = String(data: data, encoding: .utf32LittleEndian)!
        }
    }
    

    并将其用作

    let myUInt32Array: [UInt32] = [72, 101, 108, 108, 111, 128049, 127465, 127466]
    let myString = String(utf32chars: myUInt32Array)
    print(myString) // Hello???
    

    为了完整起见,通用转换器 来自https://stackoverflow.com/a/24757284/1187415

    extension String {
        init?<C : UnicodeCodec>(codeUnits:[C.CodeUnit], codec : C) {
            var codec = codec
            var str = ""
            var generator = codeUnits.makeIterator()
            var done = false
            while !done {
                let r = codec.decode(&generator)
                switch (r) {
                case .emptyInput:
                    done = true
                case .scalarValue(let val):
                    str.unicodeScalars.append(val)
                case .error:
                    return nil
                }
            }
            self = str
        }
    }
    

    可用于 UTF-8、UTF-16 和 UTF-32 输入。在你的情况下,它会是

    let myUInt32Array: [UInt32] = [72, 101, 108, 108, 111, 128049, 127465, 127466]
    let myString = String(codeUnits: myUInt32Array, codec : UTF32())!
    print(myString) // Hello???
    

    【讨论】:

    • 感谢您的回答。我有几个后续问题。 (1) 我应该什么时候选择使用基础课程而不是我给出的答案? (2) 我已经阅读并了解了一些关于big endian and little endian byte order 的内容。但是在您的答案中使用NSUTF32LittleEndianStringEncoding 背后的原因是什么?将字符串保存到文件或通过网络发送时是否需要更改任何内容?如果我只使用 Swift 类,我可以避免担心大/小端编码吗?
    • @Suragch: 1) 我不认为一个比另一个有明显的优势。我已经展示了 NSData/NSString 方法作为替代方法,因为它的代码少一些,但是您的方法也可以。 (这也是我觉得你的悬赏问题很难回答的原因:所有这些方法都有效,所以你可以选择你觉得最熟悉的方法。)
    • @Suragch: 2) 当前所有的 OS X 和 iOS 设备都使用 little-endian 在内存中存储整数,因此使用 NSUTF32LittleEndianStringEncoding。当然,如果您通过网络将数据发送到具有可能不同字节顺序的其他设备,那么您必须注意这一点。但这通常是有效的,与您当前的问题无关。
    • @l--marcl:我已经更新了当前 Swift 的代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-01
    • 2016-09-02
    • 2017-10-05
    • 2015-03-15
    • 2014-10-24
    • 2017-05-31
    • 1970-01-01
    相关资源
    最近更新 更多