(Отчасти это из комментариев, но я пытаюсь собрать их вместе и описать решения.)
Во-первых, ваши строки не в формате UTF-8.Это UTF-16 или неправильно сформированный UTF-16.Иногда UTF-16 интерпретируется как UTF-8, но когда это так, в строке будут разбросаны символы NULL.В вашем «рабочем» примере это не совсем работает.
let toApostrophe = "ACAAKgBVAFMAQQAqACAn" // *USA* '//
if let textData = Data(base64Encoded: toApostrophe) {
if let decodedString = String(data: textData, encoding: .utf8) {
print(decodedString)
print(decodedString.count)
print(decodedString.map { $0.unicodeScalars.map { $0.value } } )
} else {
print("DID NOT DECODE UTF8")
}
} else {
print("DID NOT DECODE BASE64")
}
Отпечатки:
*USA* '
15
[[0], [32], [0], [42], [0], [85], [0], [83], [0], [65], [0], [42], [0], [32], [39]]
Обратите внимание, что длина строки составляет 15 символов, а не 8, как вы, вероятно, ожидали.Это потому, что он включает в себя дополнительный невидимый NULL (0) между большинством символов. Однако
toEndBracket
не является допустимым UTF-8.Вот его байты:
["00", "20", "00", "2a", "00", "55", "00", "53", "00", "41"," 00 "," 2a "," 00 "," 20 "," 27 "," 96 "," 00 "," 20 "," d8 "," 3c "," 00 "," 22 ",«00», «7d», «00», «5d», «00»]
Это нормально, пока не достигнет 0xd8.Это начинается с битов 110, которые указывают, что это начало двухбайтовой последовательности.Но следующий байт 0x3c, который не является допустимым вторым байтом многобайтовой последовательности (он должен начинаться с 10, но начинается с 00).Поэтому мы не можем декодировать это как UTF-8.Даже использование decodeCString(_:as:repairingInvalidCodeUnits)
не может декодировать эту строку, потому что она заполнена встроенными значениями NULL.Вы должны декодировать его, используя хотя бы правильную кодировку.
Но давайте сделаем это.Декодировать как UTF-16.По крайней мере, это близко, хотя это слегка недействительный UTF-16.
let toEndBracket16 = String(data: toEndBracketData, encoding: .utf16)
// " *USA* ➖ �"}]"
Теперь мы можем по крайней мере работать с этим.Это неверный JSON, хотя.Таким образом, мы можем убрать это, отфильтровав это:
let legalJSON = String(toEndBracket16.filter { $0 != "\u{FFFD}" })
// " *USA* ➖ "}]"
Я действительно не рекомендую этот подход.Он невероятно хрупок и основан на неправильном вводе.Исправьте ввод.Но в мире, где вы пытаетесь разобрать неверный ввод, это инструменты.