Swift URL.path изменяет кодировку символов utf-8 - PullRequest
0 голосов
/ 01 ноября 2018

Почему преобразование String в URL в Swift 4.2, а затем преобразование URL обратно в String с использованием url.path изменяет кодировку специальных символов, таких как немецкие умляуты (ä, ö, ü ), даже если я использую кодировку utf-8?

Я написал пример кода, чтобы показать мою проблему. Я закодировал строки в base64, чтобы показать, что есть разница.

У меня также есть похожая нерешенная проблема со специальными символами и быстрым здесь .

Пример кода

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 различаются.

"L3BhdGgvdG8vZmlsZQ ==" для base64

"L3BhdGgvdG8vZmlsZQ ==" для base64Url

"L3BhdGgvdG8vZmlsZS93aXRoL3VtbGF1dHMvdGVzdMOkw7bDvA ==" для base64Umlauts

"L3BhdGgvdG8vZmlsZS93aXRoL3VtbGF1dHMvdGVzdGHMiG / MiHXMiA ==" для base64UrlUmlauts

Когда я помещаю строки base64Umlauts и base64UrlUmlauts в онлайн-декодер Base64, они оба показывают /path/to/file/with/umlauts/testäöü, но ä, ö, ü отличаются (не визуально).

1 Ответ

0 голосов
/ 01 ноября 2018

stringUmlauts.utf8 использует символы Unicode äöü.

Но urlUmlauts.path.utf8 использует символы Unicode aou, за которыми следует объединение ¨.

Вот почему вы получаете другую кодировку base64 - символы выглядят одинаково, но фактически кодируются по-разному.

Что действительно интересно, так это то, что Array(stringUmlauts) и Array(urlUmlauts.path) одинаковы. Разница не появится, пока вы не выполните кодировку UTF-8 с точно такими же значениями String.

Поскольку кодировка 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...