Проблема с кодировками. В Encoding.Convert есть баг?

236
29 апреля 2017, 20:21

В общем, на работе стоит русская Windows 7, а дома английский Windows 10, так вот на работе с кодировками проблем нету, а дома какие-то кракозябры.

Попробовал вот таким способом подобрать нужную кодировку, но не получилось:

        string srcStr = "êàíäèäàò";
        string pattern = "кандидат";
        foreach (var src in Encoding.GetEncodings())
        {
            foreach (var dst in Encoding.GetEncodings())
            {
                var tmp = dst.GetEncoding()
                     .GetString(Encoding.Convert(src.GetEncoding(), dst.GetEncoding(),
                         src.GetEncoding().GetBytes(srcStr)));
                if (tmp== pattern)
                {
                    Console.WriteLine($"{src.CodePage}=>{dst.CodePage}");
                }
            }
        }

Хотя вот этот сайт четко определяет нужную кодировку http://www.online-decoder.com/ru

Однако, когда я пытаюсь воспользоваться явно, то опять получаю кракозябры.

Подскажи, в чем мой косяк? Может быть в настройках Win что-нибудь поменять нужно?

В домашней ОС стоит русская локаль для программ без Unicode.

Вообще на работе вот такая строчка работает:

currentText = Encoding.UTF8.GetString(Encoding.Convert(Encoding.Default, Encoding.UTF8, Encoding.Default.GetBytes(currentText)));

а вот дома каракули на выходе.

Хм...

А вот если так, то кодировка нормально подбирается:

  string srcStr = "êàíäèäàò";
            string pattern = "кандидат";
            foreach (var src in Encoding.GetEncodings())
            {
                foreach (var dst in Encoding.GetEncodings())
                {
                    var dstBytes = src.GetEncoding().GetBytes(srcStr);
                    var tmp = dst.GetEncoding().GetString(dstBytes);
                    if (tmp == pattern)
                    {
                        Console.WriteLine($"{src.DisplayName}=>{dst.DisplayName}");
                    }
                }
            }

Разве первый вариант не идентичный последнему варианту?

Answer 1

Ваши варианты неидентичны.

Логика второго понятна: мы из байтов получили неправильную строку, интерпретируя их в неправильной кодировке. Мы получаем эти байты назад, и интерпретируем в правильной кодировке. При этом, понятно, байты не меняются, потому что это по сути одни и те же байты, мы лишь меняем их интерпретацию.

А ваш первый вариант меняет байты при помощи Convert, понятно, что он не равносилен второму. Метод Convert работает наоборот: он берёт байты, соответствующие строке в одной кодировке, и превращает их в байты той же строки в другой кодировке. То есть

var bytes2 = Encoding.Convert(enc1, enc2, bytes);

равносильно

var s = enc1.GetString(bytes);
var bytes2 = enc2.GetBytes(s);

Итого: Convert даёт байты другой кодировки для той же строки, а второй вариант даёт другую строку для тех же байтов.

READ ALSO
Потеря данных при извлечении из БД MS SQL

Потеря данных при извлечении из БД MS SQL

Есть метод с запросом к БД:

251
Передача доп.параметров в System.Text.RegularExpressions.Regex.Replace

Передача доп.параметров в System.Text.RegularExpressions.Regex.Replace

Как передать в MatchEvaluator доппараметры

285
TwoWay Binding для Dictionary<Enum, bool?>

TwoWay Binding для Dictionary<Enum, bool?>

Есть несколько checkbox'ов с тремя состояниями: включено, исключено, не установлено

303
Имя таблицы через переменную в запросе Mysql

Имя таблицы через переменную в запросе Mysql

Есть множество однотипных таблиц, различных только по именам и даннымКоличество столбцов и их названия идентичны

360