Win1251 to utf8: c# — Как перевести текст из 1251 в utf-8

Как перекодировать Windows-1251 в UTF8 в Go без страданий • Ivan Feofanov

Ниже история одной моей довольно забавной ошибки. Воистину, программист никогда не заскучает; даже имея в руках идеальный инструмент, он сможет применить его неправильно. Что уж говорить об инструментах неидеальных?

Может показаться удивительным, но в просвещённом 2020-ом году всё ещё существуют разработчики, которые полагают, что нет ничего криминального в использовании кодировки windows-1251 при отдаче с эндпойнта API контента, содержащего кириллицу. Бог им судья, мне же пришлось искать способ этот самый контент безболезненно конвертнуть в благословенный юникод.

Забегая вперёд скажу, что задача, по сути, была примитивнейшая, однако я был бы не я, если бы не устроил себе цирк на ровном месте.

Итак, берём входящие байты и конвертим их в юникод (обработка ошибок и прочие закрытия body убраны для краткости).

dec := charmap.Windows1251.NewDecoder()
out, _ := dec. Bytes(a)
var meter dmc.Meter
_ = json.Unmarshal(out, &meter)
log.Print(meter.MeterName)

Что я ожидал увидеть? “ЭЛЕКТРОСНАБЖЕНИЕ”(я кажется, не упоминал, что работаю в ЖЭКе). А что я увидел? “пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ”

Признаться, результат меня озадачил и я кинулся искать, где и то пошло не так, однако все предлагаемые гуглом способы давали неизменно один и тот же результат. Начальник едко отметил, что процесс у меня идемпотентный — какой бы способ перекодировки не применялся, получается неизменно говно, и ушёл домой, я же остался чесать в затылке.

Тут меня осенило — если от смены способа перекодировки результат не меняется, значит, проблема прячется где-то в другом месте. Минут пятнадцать я пытался понять, могут ли разработчики того самого API присылать в хедере кодировку Windows-1251, а в тексте что-либо другое, однако Postman убедил меня, что, по крайней мере, тут всё честно — контент закодирован именно в Windows-1251.

Тогда я решил проследить весь путь данных, от получения до вывода в консоль и почти сразу принялся драть волосы из бороды, проклиная собственную тупость.

Следите за руками. Контент приходит в формате json, такой вот структуры:

{
    "contents": [],
    "result": {
        "code": 1,
        "message": "some message"
    }
}

Поскольку я использую строго типизированный Go, и меня больше интересует не служебная информация, а тот самый контент, то данные проходят следующую обработку (я опускаю нерелевантный заметке код):

type Result struct {
	Code    int
	Message string
}
type Response struct {
	Contents []interface{}
	Result   Result
}
content := [][]byte{}
var response Response
_ = json.Unmarshal(res_body, &response)
for _, item := range response.Contents {
    item_bytes, _ := json.Marshal(item)
    content = append(content, item_bytes)
}

И вот этот самый content и есть то, с чем уже можно работать, маршалить его в структуры, отправлять письмом на деревню дедушке, и т. д., но вот тут-то и спряталась ошибка: первый анмаршаллинг пришедших байтов сконвертил кириллицу в совершенно нечитаемые иероглифы, поскольку корректно он умеет работать только с юникодом. А далее я получившиеся каракули собственноручно смаршалил в байты и попытался сконвертировать заранее нечитаемые символы в юникод и вполне ожидаемо получил на выходе именно его — говно на лопате.

Как понимаете, после того, как я перенёс перекодирования данных в самое начало, сразу после после их получения, ситуация исправилась:

resp, _ := client.Get(url)
res_body, _ := ioutil.ReadAll(resp.Body)
dec := charmap.Windows1251.NewDecoder()
out, _ := dec.Bytes(res_body)
content := [][]byte{}
var response Response
err = json.Unmarshal(out, &response)
for _, item := range response.Contents {
    item_bytes, _ := json.Marshal(item)
    content = append(content, item_bytes)
}
// ----
var meter dmc.Meter
_ = json.Unmarshal(out, &meter)
log.Print(meter.MeterName) //--> ЭЛЕКТРОСНАБЖЕНИЕ

Надеюсь, эта заметка поможет вам избежать подобной ошибки.

как перекодировать файлы в UTF-8 из windows-1251, koi-8 и других — Code Depth

В общем случае, перекодировать можно в любом направлении, не обязательно именно в utf-8. Можно перекодировать между кириллическими кодировками, например, из koi-8 в cp1251, из utf-8 в koi-8, из utf-8 в cp1251 и обратно. Также рассмотрим ситуацию когда нужно изменить кодировку файлов не только в текущей директории, но и во вложенных.

В Linux перекодировку файлов удобно делать утилитами recode или enconv. Есть и другие перекодировщики, но про них пусть кто-то другой напишет.

Установить recode:

sudo yum install recode

Для использования enconv нужно установить пакет enca:

sudo yum install enca

Обе команды — recode и enconv — имеют кучу возможных опций, в простейших случаях для перекодирования одного или нескольких файлов в одной директории использование такое:

recode cp1251..utf8 myfile.txt
recode cp1251..utf8 *.txt
enconv -L russian -x utf8 myfile. txt
enconv -L russian -x utf8 *.txt

На что следует обратить внимание: для команды recode надо указать направление перекодировки (как минимум, исходную кодировку, в примере это cp1251; если не указана конечная кодировка, то программа заглянет в переменные окружения LC_ALL, LC_CTYPE, LANG). Для enconv указывать направление перекодировки необязательно вообще: программа способна определить исходную кодировку, проанализировав текст файла, а конечная кодировка будет взята из переменных окружения.

То есть, если надо перекодировать файлы в вашу «обычную» кодировку, используемую в системе, примеры могут выглядеть так:

recode cp1251 *.txt
enconv -L russian *.txt

Для того, чтобы программа enconv точнее могла определить исходную кодировку файла, ей можно помочь, подсказав, на каком языке написан текст в файле. В нашем примере указан русский язык: «-L russian».

Список языков, известных программе, можно посмотреть так:

enca --list languages

enca — это не опечатка. Программа enconv является частью пакета enca.

Результат:

 belarusian: CP1251 IBM866 ISO-8859-5 KOI8-UNI maccyr IBM855 KOI8-U
 bulgarian: CP1251 ISO-8859-5 IBM855 maccyr ECMA-113
 czech: ISO-8859-2 CP1250 IBM852 KEYBCS2 macce KOI-8_CS_2 CORK
 estonian: ISO-8859-4 CP1257 IBM775 ISO-8859-13 macce baltic
 croatian: CP1250 ISO-8859-2 IBM852 macce CORK
 hungarian: ISO-8859-2 CP1250 IBM852 macce CORK
 lithuanian: CP1257 ISO-8859-4 IBM775 ISO-8859-13 macce baltic
 latvian: CP1257 ISO-8859-4 IBM775 ISO-8859-13 macce baltic
 polish: ISO-8859-2 CP1250 IBM852 macce ISO-8859-13 ISO-8859-16 baltic CORK
 russian: KOI8-R CP1251 ISO-8859-5 IBM866 maccyr
 slovak: CP1250 ISO-8859-2 IBM852 KEYBCS2 macce KOI-8_CS_2 CORK
 slovene: ISO-8859-2 CP1250 IBM852 macce CORK
 ukrainian: CP1251 IBM855 ISO-8859-5 CP1125 KOI8-U maccyr
 chinese: GBK BIG5 HZ
 none:

Для рекурсивного изменения кодировки файлов надо привлечь команду find, затем перекодировать то, что она нашла.

Среди множества опций команды find имеется набор для выполнения действий над найденными файлами. Нас интересует опция «-exec command {} ;».

Здесь:

command — команда, которую надо выполнить для каждого найденного файла;

{} — вместо скобок будет подставлено имя файла, найденного командой find;

; — точка с запятой указывает для команды find, в каком месте заканчиваются параметры команды command.

Надо иметь в виду, что «{}» и «;» может понадобиться экранировать с помощью одинарных кавычек или «\», чтобы предотвратить интерпретацию командной оболочкой (shell expansion).

Собираем всё вместе. Чтобы перекодировать из cp1251 (windows-1251) в utf-8 рекурсивно в поддиректориях все файлы, имена которых заканчиваются на ‘.txt’, надо выполнить:

find /path/to/dir -name '*.txt' -exec recode cp1251..utf8 '{}' \;

или

find /path/to/dir -name '*.txt' -exec enconv -L russian -x utf8 '{}' \;

Ура!

Понравилось это:

Нравится Загрузка…

Кодировка

символов. Как преобразовать текстовый файл в UTF-8 из Windows-1251?

спросил

Изменено 2 года назад

Просмотрено 11 тысяч раз

Windows 10, Emacs 25.

Когда я хочу преобразовать файл из Windows-1251 в UTF-8, я использую Notepad++.

Перед преобразованием:

преобразованием:

после преобразования:

Мой вопрос: возможно ли это преобразование в Emacs?

  • character-encoding

Следует использовать команду set-buffer-file-coding-system ( C-x RET f ), установить кодировку, а затем сохранить файл.

Обратите внимание, что вам может понадобиться сначала revert-buffer-with-coding-system ( C-x RET r ) перед выполнением вышеуказанного шага, если файл изначально открыт с неправильной кодировкой.

1

Самый простой способ сделать это:

  1. Тип C-x RET c
  2. Выберите нужную систему кодирования (в данном случае возможно utf-8-dos )
  3. Передайте C-x C-w в качестве команды и передайте имя файла для записи
3

Это должно помочь:

  1. Посетите файл с С-х С-f .
  2. Вернуть открытый буфер к исходной кодировке файла ( cp-1251 in в этом случае) с M-x + revert-buffer-wth-coding-system .
  3. Используйте M-x + set-buffer-file-coding-system , чтобы установить кодировку utf-8.
  4. Сохраните файл.
1

Зарегистрируйтесь или войдите в систему

Зарегистрируйтесь с помощью Google

Зарегистрироваться через Facebook

Зарегистрируйтесь, используя электронную почту и пароль

Опубликовать как гость

Электронная почта

Требуется, но не отображается

Опубликовать как гость

Электронная почта

Требуется, но не отображается

Нажимая «Опубликовать свой ответ», вы соглашаетесь с нашими условиями обслуживания и подтверждаете, что прочитали и поняли нашу политику конфиденциальности и кодекс поведения.

golang демонстрация проблемы с кодировкой utf8 win1251 · GitHub

основной пакет
импорт (
«фмт»
«golang.org/x/text/encoding/charmap»
)
основная функция () {
для я := 0; я <= 255; я++ {
символ := uint8(i)
ориг := []uint8{charnum}
utf8: = DecodeWindows1251 (оригинал)
win1251: = EncodeWindows1251 (utf8)
, если строка (оригинал)! = строка (win1251) {
fmt. Printf(«О~.. Ошибка в charnum 0x%x\n», i)
fmt.Printf(«(оригинал, utf8, win1251)\n»)
fmt.Printf(«строка: %s, %s, %s\n», строка (оригинал), строка (utf8), строка (win1251))
fmt.Printf(«в кавычках: %+q, %+q, %+q\n», строка (оригинал), строка (utf8), строка (win1251))
fmt.Printf(«hex: % x, % x, % x\n», строка (оригинал), строка (utf8), строка (win1251))
}
}
}
функция DecodeWindows1251(ba []uint8) []uint8 {
дес: = charmap.
Оставить комментарий

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

© 2019 Штирлиц Сеть печатных салонов в Перми

Цифровая печать, цветное и черно-белое копирование документов, сканирование документов, ризография в Перми.