Преобразовать код Emoji UTF-8 (байты) в значок Emoji как текст - PullRequest
0 голосов
/ 18 мая 2018

Я получаю нижеприведенную строку в ответ от WS API, когда они отправляют emoji в виде строки:

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

Я хочу, чтобы она была преобразована в значок Emoji, подобный этому -> Hii ?

Я думаю, что это происходит в формате UTF-8, как показано на рисунке ниже: Юникод изображения enter image description here

IЯ попытался декодировать его онлайн, используя UTF-8 Decoder

И я получил смайлик, успешно декодированный

Перед декодированием:

enter image description here

После декодирования: enter image description here

Но проблема здесь заключается в том, что я незнаю, как с ним работать в Swift.

Я ссылался по следующей ссылке, но она у меня не сработала.

Быстрое кодирование / декодирование смайликов

Любая помощь будет оценена.

Спасибо.

Ответы [ 2 ]

0 голосов
/ 18 мая 2018

Я исправляю вашу проблему, но нужно сделать больше, чтобы сделать ее общей, проблема здесь в том, что ваш 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 ?

            }
0 голосов
/ 18 мая 2018

Как вы уже дали ссылку на инструмент конвертера, который явно выполняет кодирование и декодирование 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);

Вывод: Hii ?


Swift

Я могу конвертировать \\xF0\\x9F\\x98\\x81 в ? в SWift.Сначала я преобразовал шестнадцатеричную строку в Data, а затем обратно в String, используя UTF-8 кодировку.

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

Вывод: ?

Ниже приведена функция, которую я использовал для преобразования шестнадцатеричной строки в данные.Я следовал этому ответу .

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} regex, потому что он также сканирует 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)

Я сделал расширение String, в котором я проверяю каждые 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())

Добро пожаловать в SP19! ?

...