Быстрое удаление PercentEncoding не работает со строкой gb2312
Сервер возвращает строку gb2312, которая была обработана функцией urlencode:
% D7% CF% BD% FB% B3% C7% C4% А7%D6%E4_%CE%DE%CF%DE%D0%A1%CB%B5%CD-%F8_www.55x.cn.rar
Как декодировать его обратно в строку gb2312:
紫禁城 魔咒 _ 无限 小说 网 _www.55x.cn.rar
3 ответа
Процентное кодирование в других кодировках, отличных от UTF-8, не считается рекомендуемым способом в недавнем мире www, поэтому вам может потребоваться осуществить такое преобразование самостоятельно.
Это может быть что-то вроде этого:
extension String.Encoding {
static let gb_18030_2000 = String.Encoding(rawValue: CFStringConvertEncodingToNSStringEncoding(CFStringEncoding(CFStringEncodings.GB_18030_2000.rawValue)))
}
extension String {
func bytesByRemovingPercentEncoding(using encoding: String.Encoding) -> Data {
struct My {
static let regex = try! NSRegularExpression(pattern: "(%[0-9A-F]{2})|(.)", options: .caseInsensitive)
}
var bytes = Data()
let nsSelf = self as NSString
for match in My.regex.matches(in: self, range: NSRange(0..<self.utf16.count)) {
if match.rangeAt(1).location != NSNotFound {
let hexString = nsSelf.substring(with: NSMakeRange(match.rangeAt(1).location+1, 2))
bytes.append(UInt8(hexString, radix: 16)!)
} else {
let singleChar = nsSelf.substring(with: match.rangeAt(2))
bytes.append(singleChar.data(using: encoding) ?? "?".data(using: .ascii)!)
}
}
return bytes
}
func removingPercentEncoding(using encoding: String.Encoding) -> String? {
return String(data: bytesByRemovingPercentEncoding(using: encoding), encoding: encoding)
}
}
let origStr = "%D7%CF%BD%FB%B3%C7%C4%A7%D6%E4_%CE%DE%CF%DE%D0%A1%CB%B5%CD%F8_www.55x.cn.rar"
print(origStr.removingPercentEncoding(using: .gb_18030_2000)) //->Optional("紫禁城魔咒_无限小说网_www.55x.cn.rar")
Ответ ООПера великолепен. недавно я тоже столкнулся с этой проблемой и нашел этот пост. Я придумал функцию для выполнения обратной операции. надеюсь, это поможет кому-то еще.
func urlencode(using encoding: String.Encoding = .gb_18030_2000) -> String? {
var res = ""
let allowedSet = NSMutableCharacterSet()
allowedSet.formUnion(with:CharacterSet.urlQueryAllowed)
// I need to filter the `&` char as well. change it for your needs.
allowedSet.removeCharacters(in: "&")
let allowed = allowedSet as CharacterSet
if let data = src.data(using: encoding) {
res = data.reduce(into:res) {
let scalar = UnicodeScalar($1)
if $1 <= 127, allowed.contains(scalar) {
$0 += String(Character(scalar))
} else {
$0 += String(format:"%%%02X", $1)
}
}
}
return res.isEmpty ? self : res
}
NSString включает эту функциональность в устаревшую функцию.
https://developer.apple.com/documentation/foundation/nsstring/1407783-replacingpercentescapes