为什么在Swift 4.2中将String
转换为URL
,然后使用URL
将String
转换回url.path
会改变特殊编码即使我使用utf-8编码,还是像德国变音符号(ä,ö,ü)这样的字符?
我写了一些示例代码来展示我的问题。我将字符串编码为base64,以显示它们之间的区别。
我也遇到类似的未解决问题,即特殊字符和快捷的here。
let string = "/path/to/file"
let stringUmlauts = "/path/to/file/with/umlauts/testäöü"
let base64 = Data(string.utf8).base64EncodedString()
let base64Umlauts = Data(stringUmlauts.utf8).base64EncodedString()
print(base64, base64Umlauts)
let url = URL(fileURLWithPath: string)
let urlUmlauts = URL(fileURLWithPath: stringUmlauts)
let base64Url = Data(url.path.utf8).base64EncodedString()
let base64UrlUmlauts = Data(urlUmlauts.path.utf8).base64EncodedString()
print(base64Url, base64UrlUmlauts)
base64
和base64Url
字符串保持不变,但base64Umlauts
和base64UrlUmlauts
不同。
“
base64
的“ L3BhdGgvdG8vZmlsZQ ==”“
base64Url
的“ L3BhdGgvdG8vZmlsZQ ==”“
base64Umlauts
的” L3BhdGgvdG8vZmlsZS93aXRoL3VtbGF1dHMvdGVzdMOkw7bDvA ==““
base64UrlUmlauts
的L3BhdGgvdG8vZmlsZS93aXRoL3VtbGF1dHMvdGVzdGHMiG / MiHXMiA ==“
当我将base64Umlauts
和base64UrlUmlauts
字符串放入在线Base64解码器中时,它们都显示/path/to/file/with/umlauts/testäöü
,但是ä, ö, ü
是不同的(不是视觉上的)。
答案 0 :(得分:3)
stringUmlauts.utf8
使用Unicode字符äöü
。
但是urlUmlauts.path.utf8
使用Unicode字符aou
,每个后跟组合的¨
。
这就是为什么您获得不同的base64编码的原因-字符看起来相同,但实际上编码不同。
真正有趣的是Array(stringUmlauts)
和Array(urlUmlauts.path)
是相同的。直到对其他完全相同的String
值执行UTF-8编码后,差异才会出现。
由于base64编码无关紧要,因此这里的测试更为简洁:
let stringUmlauts = "/path/to/file/with/umlauts/testäöü"
let urlUmlauts = URL(fileURLWithPath: stringUmlauts)
print(stringUmlauts, urlUmlauts.path) // Show the same
let rawStr = stringUmlauts
let urlStr = urlUmlauts.path
print(rawStr == urlStr) // true
print(Array(rawStr) == Array(urlStr)) // true
print(Array(rawStr.utf8) == Array(urlStr.utf8)) // false!!!
那么两个相等的字符串的UTF-8编码有何不同?
一种解决方案是在precomposedStringWithCanonicalMapping
的结果上使用path
。
let urlStr = urlUmlauts.path.precomposedStringWithCanonicalMapping
现在,您从true
中获得>
print(Array(rawStr.utf8) == Array(urlStr.utf8)) // now true