【问题标题】:How to decode a UTF16 string into a Unicode character如何将 UTF16 字符串解码为 Unicode 字符
【发布时间】:2017-11-23 16:12:47
【问题描述】:

设备对字符串“????????”进行编码作为"\uD83E\uDD1B\uD83C\uDFFD"。此字符串中表示的十六进制数字来自字符的 UTF-16 十六进制编码。 Unicode 代码点 U+1F91B, U+1F3FD 从 UTF-32 十六进制编码中获取其编号。

在后面的那个,在 Swift 中我们可以做一个像这样的字面量 "\u{1F91B}\u{1F3FD}" 我们会得到字符 "????????"正如预期的那样。

如何将 UTF-16 十六进制字符串 "\uD83E\uDD1B\uD83C\uDFFD" 转换为“????????”?

我尝试获取字符串并将其转换为 [UInt32] 32 位整数数组,然后使用它来创建 unicode 标量,但这仅适用于可以表示为单个 UTF-32 代码点的 Unicode 字符.

这是我正在使用的源代码。

extension String {

    func decodeBlock() -> String {
        let strings = self.components(separatedBy: "\\u")
        var scalars : [UInt32] = []
    
        var value: UInt32 = 0
        for string in strings {
            print(string)
            let scanner = Scanner(string: string)
            if scanner.scanHexInt32(&value) {
                scalars.append(value)
            }
        }
    
        let utf32chars = scalars
        var str = ""
        var generator = utf32chars.makeIterator()
        var utf32 : UTF32 = UTF32()
        var done = false
        while !done {
            let r = utf32.decode(&generator)
            switch (r) {
            case . emptyInput:
                done = true
            case .scalarValue(let val):
                str.append(Character(val))
            case .error:
                return "$"
            }
        }
        return str
    

        return self
    }
}

它改编自类似问题的答案中的代码。 https://stackoverflow.com/a/41412056/731773

编码字符串的来源是 org.apache.commons.lang.StringEscapeUtils escapeJava 函数,可以在 here 找到。

【问题讨论】:

    标签: swift unicode-string unicode-escapes


    【解决方案1】:

    这有点作弊,但UTF-16恰好是NSString使用的编码,所以你可以借用NSString的方法来实现它:

    extension String {
        func decodeBlock() -> String? {
            var chars = [unichar]()
    
            for substr in self.components(separatedBy: "\\u") where !substr.isEmpty {
                if let value = UInt16(substr, radix: 16) {
                    chars.append(value)
                } else {
                    return nil
                }
            }
    
            return NSString(characters: chars, length: chars.count) as String
        }
    }
    
    if let decoded = "\\uD83E\\uDD1B\\uD83C\\uDFFD".decodeBlock() {
        print(decoded)
    } else {
        print("Cannot decode")
    }
    

    【讨论】:

    • 这是尝试这样做的方法之一。但我不知道NSString(characters: chars, length: chars.count)。这正是我所需要的。谢谢!
    【解决方案2】:

    这绝对是作弊,因为它只是使用了 JavaScript 中的内置方法,但它确实有效。

    func decode() -> String{
        // getting a JSContext
        let context = JSContext()
        let encodedString = self
        // defining a JavaScript function
        let jsFunctionText = "var decode = function(encodedString) {\n" +
            "var r = /\\\\u([\\d\\w]{4})/gi;\n" +
            " x = encodedString\n" +
            "x = x.replace(r, function (match, grp) {\n" +
            "     return String.fromCharCode(parseInt(grp, 16)); } );\n" +
            " x = unescape(x);\n" +
            " return x\n" +
        "}"
        //    print(jsFunctionText)
        context!.evaluateScript(jsFunctionText)!
    
        // calling a JavaScript function
        let jsFunction = context?.objectForKeyedSubscript("decode")
    
        let decodedValue = jsFunction?.call(withArguments: [encodedString]);
        if let decodedString = decodedValue?.toString() {
            return decodedString
        } else {
            return self
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-01
      • 1970-01-01
      相关资源
      最近更新 更多