跟進我以前關于 UTF-8 文字的帖子的問題:
已經確定您可以從這樣的字串中解碼 UTF-8 文字,它只包含 UTF-8 文字:
let s = "\\xc3\\xa6"
let bytes = s
.components(separatedBy: "\\x")
// components(separatedBy:) would produce an empty string as the first element
// because the string starts with "\x". We drop this
.dropFirst()
.compactMap { UInt8($0, radix: 16) }
if let decoded = String(bytes: bytes, encoding: .utf8) {
print(decoded)
} else {
print("The UTF8 sequence was invalid!")
}
但是,這只適用于字串僅包含 UTF-8 文字的情況。當我獲取包含這些 UTF-8 文字的 Wi-Fi 名稱串列時,我該如何解碼整個字串?
例子:
let s = "This is a WiFi Name \\xc3\\xa6 including UTF-8 literals \\xc3\\xb8"
與預期的結果:
print(s)
> This is a WiFi Name ? including UTF-8 literals ?
在 Python 中,有一個簡單的解決方案:
contents = source_file.read()
uni = contents.decode('unicode-escape')
enc = uni.encode('latin1')
dec = enc.decode('utf-8')
在 Swift 5 中是否有類似的方法來解碼這些字串?
uj5u.com熱心網友回復:
據我所知,沒有原生的 Swift 解決方案。為了使它看起來像呼叫站點上的 Python 版本一樣緊湊,您可以構建一個擴展String來隱藏復雜性
extension String {
func replacingUtf8Literals() -> Self {
let regex = #"(\\x[a-zAZ0-9]{2}) "#
var str = self
while let range = str.range(of: regex, options: .regularExpression) {
let literalbytes = str[range]
.components(separatedBy: "\\x")
.dropFirst()
.compactMap{UInt8($0, radix: 16)}
guard let actuals = String(bytes: literalbytes, encoding: .utf8) else {
fatalError("Regex error")
}
str.replaceSubrange(range, with: actuals)
}
return str
}
}
這讓你打電話
print(s.replacingUtf8Literals()).
//prints: This is a WiFi Name ? including UTF-8 literals ?
為方便起見,我用fatalError. 您可能希望在生產代碼中以更好的方式處理這個問題(盡管,除非正則運算式錯誤,否則它永遠不會發生!)。需要在此處拋出某種形式的中斷或錯誤,否則您將陷入無限回圈。
uj5u.com熱心網友回復:
首先將解碼代碼作為計算屬性添加到字串擴展中(或創建一個函式)
extension String {
var decodeUTF8: String {
let bytes = self.components(separatedBy: "\\x")
.dropFirst()
.compactMap { UInt8($0, radix: 16) }
return String(bytes: bytes, encoding: .utf8) ?? self
}
}
然后使用正則運算式并使用while回圈匹配來替換所有匹配的值
while let range = string.range(of: #"(\\x[a-f0-9]{2}){2}"#, options: [.regularExpression, .caseInsensitive]) {
string.replaceSubrange(range, with: String(string[range]).decodeUTF8)
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/363655.html
