UTF-8 - это расширенный набор ASCII, поэтому преобразование из ASCII в UTF-8 похоже на преобразование автомобиля в транспортное средство.
+--- UTF-8 ---------------+
| |
| +--- ASCII ---+ |
| | | |
| +-------------+ |
+-------------------------+
Инструмент, на который вы ссылаетесь, использует термин "ASCII" в качестве синонима для mojibake (он говорит «машина», но означает «металлолом»). Моджибаке обычно происходит следующим образом:
Вы выбираете не-английский sh символ: ⬦
'БЕЛЫЙ СРЕДНИЙ АЛМАЗ' (U + 2B26)
Вы кодируете его, используя UTF-8: 0xE2 0xAC 0xA6
Вы открываете поток в инструменте, настроенном для использования однобайтовой кодировки, которая является широко используется в вашем регионе: Windows -1252
Вы просматриваете отдельные байты символа UTF-8 в таблице символов однобайтовых кодировка:
0xE2
-> â
0xAC
-> ¬
0xA6
-> ¦
Вы кодируете результирующие символы в UTF-8:
Таким образом вы преобразовали поток UTF-8 0xE2 0xAC 0xA6
(⬦
в) так что поток UTF-8 0xC3 0xA2 0xC2 0xAC 0xC2 0xA6
(⬦
).
Чтобы отменить это, нужно выполнить шаги в обратном порядке. Это просто, если вы знаете, какую прокси-кодировку использовали (Windows -1252 в моем примере):
$mojibake = "\xC3\xA2\xC2\xAC\xC2\xA6";
$proxy = 'Windows-1252';
var_dump($mojibake, bin2hex($mojibake));
$original = mb_convert_encoding($mojibake, $proxy, 'UTF-8');
var_dump($original, bin2hex($original));
string(6) "⬦"
string(12) "c3a2c2acc2a6"
string(3) "⬦"
string(6) "e2aca6"
Но это сложно, если вы этого не сделаете. Я думаю, вы можете:
Скомпилировать словарь различных последовательностей байтов, которые вы получаете в разных однобайтовых кодировках, а затем использовать какой-то байесовский вывод, чтобы выяснить наиболее вероятную кодировку. (Я не могу вам в этом помочь.)
Попробуйте наиболее вероятные кодировки и визуально проверьте вывод, чтобы определить, что является правильным:
// Source code saved as UTF-8
$mojibake = "Z…Z";
foreach (mb_list_encodings() as $proxy) {
$original = mb_convert_encoding($mojibake, $proxy, 'UTF-8');
echo $proxy, ': ', $original, PHP_EOL;
}
Если (как в вашем случае) вы знаете, что такое исходный текст, и уверены, что у вас нет смешанных кодировок, сделайте как # 2, но попытайтесь все кодировки PHP поддерживает:
// Source code saved as UTF-8
$mojibake = 'Z…Z';
$expected = 'Z⬦Z';
foreach (mb_list_encodings() as $proxy) {
$current = @mb_convert_encoding($mojibake, $proxy, 'UTF-8');
if ($current === $expected) {
echo "$proxy: match\n";
}
}
(Это печатает wchar: match
; не совсем уверен, что это значит.)