Как правильно конвертировать USC-2 little-endian в UTF-8?
У меня есть файл и окончания строк в стиле Windows \r\n ; он закодирован в USC-2 с прямым порядком байтов.
Скажи, что это мой файл fruit.txt (USC-2 little endian):
Так что я открываю его в std::wifstream и попробуйте разобрать содержимое:
Если я попытаюсь напечатать cout …
…Вот что он выводит:
Хуже того, если я открою его в Notepad ++, это будет выглядеть так
Я могу отчасти исправить это путем принудительного преобразования кодировки обратно в USC-2, что приводит к следующему:
мой wstring_to_string функция определяется как это:
редактировать Я думаю, что может быть ошибка с mingw64 / mingw-w64-x86_64-gcc 6.3.0-2, который предоставляется MSYS2. Я попробовал все предложения, и добавление локали в потоки просто не дает никакого вывода. Я знаю, что есть только две родные локали, «C» и «POSIX». Я собирался попробовать Visual Studio, но у меня не было достаточной скорости интернета для загрузки 4 ГБ. Я использовал ICU, как предложил @Andrei R., и он отлично работает.
Я хотел бы использовать стандартные библиотеки, но я в порядке с этим. Пожалуйста, посмотрите на мой код, если вам нужно это решение: https://pastebin.com/qudy7yva
Решение
преобразование в / из юникода вообще не так тривиально. Посмотри на ICU библиотеки, я полагаю, это наиболее полная библиотека преобразования кодировки для c / c ++.
Другие решения
Сам код в порядке, как есть.
Реальная проблема заключается в том, что ваш входной файл НЕ является допустимым UTF-16LE для начала (ваше использование std::codecvt_utf8_utf16 требуется UTF-16, а не UCS-2). Это хорошо видно на скриншотах Notepad ++.
Случайно данные файла выглядят как файл UTF-16LE с спецификацией ( ÿþ такое UTF-16LE, если рассматривать как 8-битный ANSI) как есть до конца файла UCS-2BE (или UTF-16BE), у которого не было спецификации.
Вам нужно исправить входной файл так, чтобы весь файл был действительным UTF-16LE от начала до конца (с или без спецификации спереди, а не в середине).
Тогда код, который у вас уже есть, будет работать.
Для вашего случая основная проблема заключается в том, что вы сделали wifstream прочитайте файл неправильно. Если вы напечатаете размер wstr в wstring_to_string, вы обнаружите, что это не то, что вы ожидаете.
Установите правильную локаль, чтобы решить эту проблему.
При создании патча diff с Git оболочкой в Windows (при использовании GitHub для Windows), кодировка символов патча будет UCS-2 Little Endian в соответствии с Notepad ++ (см. скриншоты ниже).
Как я могу изменить это поведение и заставить Git создавать патчи с ANSI или UTF-8 без кодировки символов спецификации?
С тех пор я также понял, что мне нужно вручную преобразовать EOL из формата Windows ( \r\n ) в UNIX ( \n ) в Notepad ++ (Edit > EOL Conversion > UNIX). Если я этого не сделаю, я получаю ошибку «trailing whitespace» (даже если все пробелы обрезаны: «TextFX» > «TextFX Edit» > «Trim Trailing Spaces» ).
Итак, шаги, которые мне нужно сделать для патча, который будет применяться:
Пожалуйста, взгляните на этот снимок экрана:
ОТВЕТЫ
Ответ 1
Результаты использования командлета Out-File могут быть не такими, какие вы ожидаете, если вы привыкли к традиционному перенаправлению вывода. Чтобы понять его поведение, вы должны знать о контексте, в котором работает командлет Out-File.
По умолчанию командлет Out-File создает файл Unicode. Это лучший дефолт в долгосрочной перспективе, но это означает, что инструменты, которые ожидают файлы ASCII, будут работать неправильно с выходным форматом по умолчанию. Вы можете изменить формат вывода по умолчанию на ASCII, используя параметр Encoding:
Форматирование содержимого файлов Out-file, чтобы он выглядел как консольный вывод. Это приводит к усечению вывода так же, как и в консольном окне в большинстве случаев. [. ]
Чтобы получить результат, который не заставляет привязки строк соответствовать ширине экрана, вы можете использовать параметр Width для указания ширины линии.
избежит проблем с кодировкой. Однако это все еще не решает проблему с линейными окончаниями Windows и Unix. Есть командлеты (см. Расширения сообщества PowerShell), чтобы выполнить преобразование строк.
Однако вся эта перекодировка не повышает мою уверенность в патче (который не имеет самой кодировки, а представляет собой просто строку байтов). Вышеупомянутый Cookbook содержит script Invoke-BinaryProcess, который можно использовать для перенаправления вывода команды без модификации.
Ответ 2
В случае, если это помогает кому угодно, использование старой старой командной строки вместо PowerShell работает безупречно; он, похоже, не страдает от каких-либо проблем, присутствующих в PowerShell в отношении кодировки символов и EOL.
Ответ 3
Если вы используете powershell, вы также можете просто сделать:
Это заставляет команду запускаться через CMD, который записывает в выходной файл как есть.
Ответ 4
Ответ 5
Выполнение dos2unix на diff, создаваемом на PowerShell, кажется, делает трюк для меня. Затем я смог apply выполнить diff.
Подскажите с кодировкой файла в UCS-2
Всем привет.
Не получается получить на выходе файл в кодировке UCS-2 LE BOM. (из win-1251)
Пробую так:
Перекодировать из UCS-2 Little Endian в UTF
Есть много файлов *.txt в кодировке (как я понял) UCS-2 Little Endian. Как перевести эти файлы в.
Считать текст из файла с кодировкой utf-16 LE
Возникла кое-какая проблема. У меня имеется xml файл, в кодировке UTF-16 LE с определенным.
Из UCS-2 Little Endian в UTF-8 без BOM
Здравствуйте! Имеется файлик xml в кодировке UCS-2 Little Endian. Хочу написать обработчик на.
Проблемы с кодировкой при подключении текстового файла
Проблема вот в чем. В файле question.txt лежит вопрос, написанный по русски, но когда в консоле я.
Эта кодировка не является «многобайтовой».
Поэтому MultiByte функции её не поддерживают.
Да и смысла в этом мало.
После применения функции StrToWStr как раз тот самый UCS-2 (то есть, UTF-16) и получается.
Остаётся только BOM вручную прицепить.
Оставил только StrToWStr, добавил BOM в начало файла. Кодировка судя по notepad++ стала верной. Но в файл текст иероглифами идет. Не пойму как правильно wstring который UTF-16 после функции содержит правильно в файл направить.
Даже не знаю какой из вариантов лучше смотрится.
Я в CodeBloks делаю там пишет, что кодировка кода w1251;
С codecvt чето не разобрался, не пошел у меня код под него. Не мгу правильно прицепить его к CodeBloks. Пишет не найден файл. Так что уж лучше альтернатива, я хоть более менее понимаю ее.
Vort_ твой первый вариант работает как надо. Единственное как в конце стоки убрать признак конца строки NUL (\0)? Программа для которой файл делаю чето упорно игнорит данные если они на него заканчиваются строки.
В общем пока как то так, добавил еще перенос на новую строку. Этот nul победить и будет отлично.
Введение
Ресурсы
Нижеприведенные ссылки как минимум полезны настолько же, насколько и данная статья, а может — и более полезны. Я сам использовал их при написании данной статьи. В них много полезных и качественных материалов, и если в этой статье вы заметите какие-нибудь неточности, то данные ресурсы должны быть более точными.
Двоичные и текстовые данные – это две разные вещи
Большинство современных языков программирования (как и некоторые старые) проводят ясную черту между двоичным (бинарным) контентом и символьным (или текстовым) контентом. Хотя эта разница понимается на инстинктивном уровне, я всё-таки внесу определение.
Бинарные (двоичные) данные являются последовательностью октетов (октет состоит из 8 битов) без всякого придаваемого им естественного значения, или интерпретации. И даже если существует внешнее «толкование» того или иного набора октетов как, скажем, исполняемый файл или графическое изображение, данные сами по себе являются просто набором октетов. Далее вместо термина «октет» я буду использовать «байт», хотя, если говорить точно, не всякий байт является октетом. К примеру, существовали компьютерные архитектуры с 9-битовыми байтами. Впрочем, в данном контексте такие детали не очень-то и нужны, так что далее под термином «байт» я буду подразумевать именно 8-битовый байт.
Символьные (текстовые) данные являются последовательностью символов.
Так для чего же Юникод?
Не волнуйтесь, если всё вышесказанное выглядит странно. О различиях, описанных выше, следует знать, но на самом деле они не часто выходят на первый план. Большинство ваших задач, скорее всего, будет «крутиться» вокруг конвертации некоего набора байтов в некий текст и наоборот. В таких ситуациях вы будете работать со структурой System.Char (в C# известна под псевдонимом char ), классом System.String ( string в C#), а также с классом System.Text.Encoding.
Структура Char является самым базовым типом символа в C#, один экземпляр Char представляет один символ Юникода и занимает 2 байта памяти, а значит, может принимать любое значение из диапазона 0-65535. Имейте в виду, что не все числа из этого диапазона являются валидными символами Юникода.
Встроенные схемы кодировок
ASCII
UTF-16 и UCS-2
UTF-7, судя по моему опыту, редко когда используется, но он позволяет перекодировать Юникод (вероятно, только первые 65535 символов) в ASCII-символы (не байты!). Это может пригодиться при работе с электронной почтой в ситуациях, когда почтовые шлюзы поддерживают только символы ASCII, или даже только подмножество ASCII (к примеру, кодировку EBCDIC). Моё описание выглядит невнятно, потому что я никогда не залазил в детали UTF-7 и не собираюсь этого делать впредь. Если вам необходимо использовать UTF-7, то вы, вероятно, и так знаете достаточно, а если у вас нет абсолютной необходимости использовать UTF-7, то советую не делать этого. Экземпляр класса для кодирования в UTF-7 может быть получен при помощи свойства Encoding.UTF7.
Кодовые страницы Windows/ANSI
Windows Code Pages (кодовые страницы Windows) являются, как правило, одно- или двухбайтными наборами символов, кодирующими до 256 или 65 536 символов соответственно. Каждая кодовая страница имеет свой номер, и кодировщик для кодовой страницы с известным номером можно получить при помощи статического метода Encoding.GetEncoding(Int32). В большинстве случаев кодовые страницы полезны для работы со старыми данными, которые часто хранятся в «кодовой странице по умолчанию» (default code page). Энкодер для кодовой страницы по умолчанию может быть получен при помощи свойства Encoding.Default. Снова таки, избегайте использования кодовых страниц, когда это возможно. За дополнительной информацией обращайтесь к MSDN.
ISO-8859-1 (Latin-1)
Потоки, ридеры и райтеры
Потоки бинарны по своей природе, они читают и записывают байты. Всё, что принимает строку, должно её определённым образом преобразовать в байты, и это преобразование может быть как успешным для вас, так и нет. Эквивалентами потоков для чтения и записи текста служат абстрактные классы System.IO.TextReader и System.IO.TextWriter соответственно. Если у вас уже есть готовый поток, вы можете использовать классы System.IO.StreamReader (который непосредственно наследует TextReader ) для чтения и System.IO.StreamWriter (который непосредственно наследует TextWriter ) для записи, передавая поток в конструктор этих классов и кодируя так, как вам нужно. Если вы явно не укажете кодировку, по умолчанию будет применена UTF-8. Ниже представлен пример кода, конвертирующего файл с UTF-8 в UCS-2:
Сложные моменты
Ладно, это были лишь основы Юникода. Есть множество других нюансов, на некоторые из которых я уже намекнул, и я считаю, что людям следует о них знать, даже если они полагают, что подобное никогда с ними не произойдёт. Я не предлагаю каких-либо общих методологий или руководящих принципов — я просто пытаюсь поднять вашу осведомленность в возможных проблемах. Ниже приведён список, и он ни скольким образом не исчерпывающий. Важно, чтобы вы поняли, что большинство описанных проблем и трудностей ни в коей мере не являются виной или ошибками Консорциума Юникода; так же, как и в случае даты, времени и любой из проблем интернационализации, это — «заслуга» человечества, которое с течением времени само создало многие принципиально сложные проблемы.
Культуро-зависимый поиск, сортировка и проч.
Суррогатные пары
Модифицирующие символы
Не все символы из Юникода в результате вывода на экран или бумагу предстают в виде значка/картинки. Подчёркнутый (акцентированный) символ может быть представлен в качестве двух других символов: обычного, неподчёркнутого символа и следующего за ним символа подчёркивания, который называется модифицирующим (или комбинируемым) символом (Combining character). Некоторые графические интерфейсы поддерживают модифицирующие символы, некоторые нет, и работа вашего приложения будет зависеть от того, какое предположение вы сделаете.
Нормализация
Частично из-за таких вещей, как модифицирующие символы, может быть несколько способов представления того, что в некотором смысле является одним символом. Литера «á» с ударением, к примеру, может быть представлена одним символом «а» без ударения и следующим за ним модифицирующим символом ударения, а может быть представлена только одним символом, представляющим готовую литеру «а» с ударением. Последовательности символов могут быть нормализованы таким образом, чтобы использовать модифицирующие символы везде, где это возможно, или же наоборот — не использовать их везде, где их можно заменить одиночным символом. Должно ли ваше приложение рассматривать две строки, содержащие литеру «á» с ударением, но в одной представленную двумя символами, а во второй одним, как равные, или как разные? А что насчёт сортировки? Производят ли сторонние компоненты и библиотеки, используемые вами, нормализацию строк, и вообще, учитывают ли подобные нюансы? На эти вопросы отвечать вам.
Отладка проблем с Юникодом
Этот раздел (в оригинале это отдельная статья – прим. пер.) описывает, что делать в очень специфических ситуациях. А именно, у вас есть некоторые символьные данные (попросту — текст) в одном месте (как правило, в базе данных), которые проходят через разные шаги/слои/компоненты и затем выводятся пользователю (как правило, на веб-странице). И, к сожалению для вас, некоторые символы отображены неверно (крякозябры). Исходя из множества шагов-этапов, по которым проходят ваши текстовые данные, проблема может возникать во многих местах. Это страница поможет вам просто и надёжно узнать, что и где «сломалось».
Шаг 1: поймите основы Юникода
А попросту говоря — прочтите основной текст статьи. Можете также обратить внимание на ссылки, которые приведены в начале статьи. Факт в том, что без базовых знаний вам будет туговато.
Шаг 2: попытайтесь определить, какие конвертации могли произойти
Если вы можете понять, где, возможно, всё ломается, то этот участок/этап намного проще будет изолировать. Вместе с тем имейте в виду, что проблема может быть не в процессе извлечения и преобразования текста из хранилища, а в том, что уже «испорченный» текст был занесён в хранилище ранее. (С подобными проблемами я стыкался в прошлом, когда, к примеру, одно старое приложение искажало текст при записи и считывании его в/из БД. «Прикол» был в том, что ошибки конвертации накладывались друг на друга и взаимокомпенсировались, так что на выходе получался корректный текст. Вообще приложение работало нормально, но стоило его тронуть — и всё рассыпалось.) К действиям, которые могут «портить» текст, следует относить выборку из БД, чтение из файла, передачу через веб-соединение и выведение текста на экран.
Шаг 3: проверяйте данные на каждом этапе
Первое правило: не доверяйте ничему, что логирует символьные данные в виде последовательности глифов (т.е. стандартных значков символов). Вместо этого вы должны логировать данные как набор кодов символов в виде байтов. Например, если я имею строку, содержащую слово «hello», то я её отображу как «0068 0065 006C 006C 006F». (Использование шестнадцатеричных кодов позволит вам легко проверить символ по кодовым таблицам.) Чтобы это сделать, надо пройтись по всем символам в строке и для каждого символа вывести его код, что и делается в нижеприведённом методе, который отображает результат в консоль:
Ваш собственный метод логирования будет иным в зависимости от вашего окружения, но основа его должна быть именно такой, как я привёл. Более продвинутый способ отладки и логирования символьных данных я привёл в своей статье, посвящённой строкам.
Суть моей идеи в том, чтобы избавиться от всевозможных проблем с кодировками, шрифтами и т.д. Эта методика может быть полезна при работе со специфичными символами Юникода. Если же вы не можете корректно логировать шестнадцатеричные коды даже простого ASCII-текста — у вас большие проблемы.
Следующий этап — убедитесь, что у вас есть тест-кейс, который можно использовать. Найдите желательно небольшой набор исходных данных, на котором ваше приложение гарантированно «сбоит», удостоверьтесь, что вы точно знаете, каким должен быть правильный результат, и залогируйте получившийся результат во всех проблемных местах.
После того, как проблемная строка залогирована, надо удостовериться, является ли она такой, какой должна быть, или нет. В этом вам поможет веб-страница Unicode code charts. Вы можете выбрать как набор символов, в котором уверены, так и искать символы в алфавитном порядке. Убедитесь, что каждый символ в строке имеет правильное значение. Как только вы найдёте то место в вашем приложении, где поток символьных данных поврежден, исследуйте это место, выясните причину ошибки и исправьте её. Исправив все ошибки, убедитесь, что приложение работает корректно.
Заключение
Как и в случае с подавляющим большинством ошибок, возникающих в разработке ПО, проблемы с текстом решаются при помощи универсальной стратегии «разделяй и властвуй». Как только вы будете уверены в каждом шаге, вы сможете быть уверенными в целом. Если во время исправления подобных ошибок вы столкнётесь с особенно непонятными и странными их проявлениями, я настоятельно советую после их исправления покрыть данный участок кода юнит-тестами; они будут служить и документацией, показывающей, что может случиться, и защитой от будущих регрессий.
Русские Блоги
Файлы реализации C ++ сохраняются как файлы ANSI / UTF-8 / UCS-2.
Надпись: Иногда унификация и стандартизация могут решить многие проблемы.
Раньше я использовал C ++ для файловых операций и сбивал меня с толку, почему китайский язык искажен? Почему он может нормально отображаться в NotePad ++, но номер строки, отображаемый в NotePad, нечеткий?
Чтобы решить вышеупомянутые проблемы и повторить надпись, единый формат кодирования может решить все головоломки. NotePad ++ поддерживает множество кодировок. NotePad, естественно, несравнимо с младшим братом. Теперь позвольте мне по очереди представить форматы кодирования, поддерживаемые младшим братом: ANSI, Unicode, Unicode big endian, UTF-8.
Сохранить как файл в кодировке ANSI
Код ANSI «Ascii» (Американский стандартный код для обмена информацией, Американский стандартный код для обмена информацией).
Хорошо, запустите приведенный выше код, и вы откроете «save_as_ansi.txt», что ж! Почему там только один[ Очевидно, не паникуйте, просто нужно удалить комментарии к контенту, и он будет отображаться нормально.
setlocale:
Заголовочный файл: locale.h
char* setlocale(int category, const char* locale)
Установите языковой стандарт для всех функций C, связанных с языком C и локальной средой. Когда вы тупо запутались или не хотите выяснять, какие функции, добавление его в код C ++ может решить потенциальную проблему.
std::locale::global:
Заголовочный файл: локаль
Оператор: статическая локаль глобальная (const locale & loc);
Замените языковой стандарт глобальной функции C ++, связанный с локальной средой, и верните исходный языковой стандарт системы.
Сохранить как файл в кодировке UTF-8
Фактически, файлы в кодировке utf-8 также можно разделить на два типа файлов, включая BOM и без BOM.Различие заключается в заголовке файла.
Реализовать его очень сложно, это очень просто, начиная с C11, но, пожалуйста, не используйте его в MAC OS7 и ниже, потому что система вообще не поддерживает C11. Вы можете использовать только API-интерфейс платформы object-c.
Разница только вcodecvt_utf8Последняя цифра параметра шаблона.
Сохранить как файл в кодировке Unicode
UCS-2 с прямым порядком байтов
По предыдущим идеям реализация очень проста, C11 готов для вас, смотритеstd::codecvt_utf16
UCS-2 Little Endian
Обратите внимание, что маска режима прямого порядка байтов становится 1 | 2, а именно:










