#c_sharp #net #кодировка #utf_8 #unicode
Программа берет содержание буфера, в котором хранится HTML, и должна сделать над ним какую-то работу. Но проблема в том, что в нем кириллица и нужно что-то делать с кодировкой… Пробовал перекодировать, но у некоторых пользователей возникают кракозябры: var bytes = Encoding.Default.GetBytes(source); return Encoding.UTF8.GetString(bytes); Пробовал HTML из буфера, который иногда вызывает кракозябры, сам прогонять через программу и у меня всё нормально. Может дело в каких-то настройках Windows? Какие существуют более универсальные варианты перекодирования? Все пользователи (в том числе и я) используют Google Chrome, а значит, что это не проблема браузера.
Ответы
Ответ 1
Понятие кодировки возникает только при сохранении строки на диск (в виде отдельных байт) или при передачи по сети (в виде байт). То, что вы считаете ситуацией "строка source в неправильной кодировке" - это ложная проблема. Т.к. проблема кодировки возникает только при преобразовании в байты - то на самом деле ваша проблема это "строка source была прочитана из массива байт с указанием неправильной кодировки". И править надо это не "перекодированием". После прочтения строки из байт с использованием неправильной кодировки нет 100% рабочего способа ее "исправить". Есть только костыли вроде "записать ее назад в байты с указанием неправильной кодировки (надеясь что байты получатся те же самые), а потом еще раз прочитать с указанием правильно". Т.е. вы пытаетесь построить цепочку: Есть байты строки в кодировке A Прочитать их как строку в кодировке B Увидеть кракозяблы Записать кракозяблы обратно с указанием кодировки B (использовать операцию, обратную (2) надеясь получить оригинальные байты, те же, что были в (1) Прочитать байты (те же, что были в (1)) в строку, но уже с указанием кодировки A Код в вашем примере делает пункты 3-5. Код для 1-2 вы не привели. При этом очевидно, что в полной цепочке пункты 2-4 избыточны, и выглядеть она как Есть байты строки в кодировке A Прочитать байты в строку с указанием кодировки A Вам нужно исправить то место, где вы читаете source из массива байт/из сети/из буфера обмена, указав в нем правильную кодировку. "Перекодирование стоит использовать только в случае, если вы получаете кривую строку сразу в виде string из стороннего источника. К сожалению, Cliboard.GetText(TextDataFormat.Html) - это именно такой источник. HTML Clipboard Format выдает содержимое в виде байт именно в UTF-8. Реализация чтения байт в HTML-строку в Cliboard выглядит вот так: if (format.Equals(DataFormats.Text) || format.Equals(DataFormats.Rtf) || format.Equals(DataFormats.OemText)) { data = ReadStringFromHandle(hglobal, false); } else if (format.Equals(DataFormats.Html)) { if (WindowsFormsUtils.TargetsAtLeast_v4_5) { data = ReadHtmlFromHandle(hglobal); } else { // This will return UTF-8 strings as an array of ANSI characters, which makes it the wrong behavior. // Since there are enough samples online how to workaround that, we will continue to return the // incorrect value to applications targeting netfx 4.0 // DevDiv2 data = ReadStringFromHandle(hglobal, false); } } Собственно, комментарий полностью объясняет поведение. при компиляции под 4.5 и более поздние фреймворки вы получите сразу валидную строку при компиляции под 4.0 и более ранние версии - вы получите получите байты в UTF-8, прочитанные как Encoding.Default, через new string((sbyte*)ptr) Соответственно, в <=4.0 ваш хак с перекодированием обязателен и полностью валиден. В >=4.5 он гаранитированно невалиден и избыточен.
Комментариев нет:
Отправить комментарий