Страницы

Поиск по вопросам

понедельник, 22 октября 2018 г.

Как получить Html из буфера обмена в формате Unicode?

Программа берет содержание буфера, в котором хранится HTML, и должна сделать над ним какую-то работу.
Но проблема в том, что в нем кириллица и нужно что-то делать с кодировкой…
Пробовал перекодировать, но у некоторых пользователей возникают кракозябры:
var bytes = Encoding.Default.GetBytes(source); return Encoding.UTF8.GetString(bytes);
Пробовал HTML из буфера, который иногда вызывает кракозябры, сам прогонять через программу и у меня всё нормально.
Может дело в каких-то настройках Windows?
Какие существуют более универсальные варианты перекодирования?
Все пользователи (в том числе и я) используют Google Chrome, а значит, что это не проблема браузера.


Ответ

Понятие кодировки возникает только при сохранении строки на диск (в виде отдельных байт) или при передачи по сети (в виде байт).
То, что вы считаете ситуацией "строка 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 он гаранитированно невалиден и избыточен.

Комментариев нет:

Отправить комментарий