将 UTF-8(字节)表情符号代码转换为表情符号图标作为文本

Convert UTF-8 (Bytes) Emoji Code to Emoji icon as a text

当 WS API 将表情符号作为字符串发送时,我收到以下字符串作为响应:

let strTemp = "Hii \xF0\x9F\x98\x81"

我想把它转换成这样的表情图标 -> Hii

我认为它以 UTF-8 格式出现,如下图所示:Image Unicode

I have tried decoding it Online using UTF-8 Decoder

表情成功解码

解码前:

解码后:

但这里的问题是我不知道如何在 Swift 中使用它。

我参考了 link 但它对我不起作用。

Swift Encode/decode emojis

如有任何帮助,我们将不胜感激。

谢谢。

正如您已经提供的 link 转换器工具,它显然在进行 UTF-8 编码和解码。您有 UTF-8 编码的字符串,所以这里是 UTF8-Decoding.

的示例

Objective-C

const char *ch = [@"Hii \xF0\x9F\x98\x81" cStringUsingEncoding:NSUTF8StringEncoding];
NSString *decode_string = [NSString stringWithUTF8String:ch];
NSLog(@"%@",decode_string);

Output: Hii


Swift

我可以在 SWift 中将 \xF0\x9F\x98\x81 转换为 </code>。 首先,我将 hexa 字符串转换为 <code>Data,然后使用 UTF-8 编码转换回 String

var str = "\xF0\x9F\x98\x81"
if let data = data(fromHexaStr: str) {
     print(String(data: data, encoding: String.Encoding.utf8) ?? "")
}

Output:

下面是我用来将十六进制字符串转换为数据的函数。我关注了 this answer.

func data(fromHexaStr hexaStr: String) -> Data? {
    var data = Data(capacity: hexaStr.characters.count / 2)
    let regex = try! NSRegularExpression(pattern: "[0-9a-f]{1,2}", options: .caseInsensitive)
    regex.enumerateMatches(in: hexaStr, range: NSMakeRange(0, hexaStr.utf16.count)) { match, flags, stop in
        let byteString = (hexaStr as NSString).substring(with: match!.range)
        var num = UInt8(byteString, radix: 16)!
        data.append(&num, count: 1)
    }

    guard data.count > 0 else { return nil }

    return data
}

注意:上面代码的问题是它只转换六角字符串而不是组合字符串。

最终工作解决方案:SWIFT

我通过使用 for 循环而不是 [0-9a-f]{1,2} 正则表达式来完成此操作,因为这也会扫描 81, 9F, Any Two digits number,这显然是错误的。

例如:I have 81 INR \xF0\x9F\x98\x81.

/// This line will convert "F0" into hexa bytes
let byte = UInt8("F0", radix: 16)

我制作了一个字符串扩展,其中我最多检查每 4 个字符是否有前缀 \x 和计数 4,最后两个字符可通过使用 radix 转换为六字节如上所述。

extension String {

    func hexaDecoededString() -> String {

        var newData = Data()
        var emojiStr: String = ""
        for char in self.characters {

            let str = String(char)
            if str == "\" || str.lowercased() == "x" {
                emojiStr.append(str)
            }
            else if emojiStr.hasPrefix("\x") || emojiStr.hasPrefix("\X") {
                emojiStr.append(str)
                if emojiStr.count == 4 {
                    /// It can be a hexa value
                    let value = emojiStr.replacingOccurrences(of: "\x", with: "")
                    if let byte = UInt8(value, radix: 16) {
                        newData.append(byte)
                    }
                    else {
                        newData.append(emojiStr.data(using: .utf8)!)
                    }
                    /// Reset emojiStr
                    emojiStr = ""
                }
            }
            else {
                /// Append the data as it is
                newData.append(str.data(using: .utf8)!)
            }
        }

        let decodedString = String(data: newData, encoding: String.Encoding.utf8)
        return decodedString ?? ""
    }
}

用法:

var hexaStr = "Hi \xF0\x9F\x98\x81 81"
print(hexaStr.hexaDecoededString())

Hi 81

hexaStr = "Welcome to SP19!\xF0\x9f\x98\x81"
print(hexaStr.hexaDecoededString())

Welcome to SP19!

我解决了你的问题,但它需要更多的工作才能使其通用,这里的问题是你的 Emijo 由 Hex Byte x9F 表示,所以我们必须将此 Hex 转换为 utf8 然后将其转换为 Data 最后将数据转换为 String

最终结果Hii 请阅读评论

 let strTemp = "Hii \xF0\x9F\x98\x81"


            let regex = try! NSRegularExpression(pattern: "[0-9a-f]{1,2}", options: .caseInsensitive)
            // get all matched hex  xF0 , x9f,..etc

            let matches = regex.matches(in: strTemp, options: [], range: NSMakeRange(0, strTemp.count))


            // Data that will hanlde convert hex to UTf8
            var emijoData = Data(capacity: strTemp.count / 2)

            matches.enumerated().forEach { (offset , check) in
                let byteString = (strTemp as NSString).substring(with: check.range)
                var num = UInt8(byteString, radix: 16)!
                emijoData.append(&num, count: 1)
            }

            let subStringEmijo = String.init(data: emijoData, encoding: String.Encoding.utf8)!
            //now we have your emijo text   we can replace by its code from string using matched ranges `first` and `last`

            // All range range of  \xF0\x9F\x98\x81 in "Hii \xF0\x9F\x98\x81" to replce by your emijo

            if let start = matches.first?.range.location, let end = matches.last?.range.location  , let endLength = matches.last?.range.length {

                let startLocation = start  - 2
                let length = end - startLocation + endLength

                let sub = (strTemp as NSString).substring(with: NSRange.init(location: startLocation, length: length))

                print( strTemp.replacingOccurrences(of: sub, with: subStringEmijo))
              // Hii 

            }