Библиотека для преобразования строк в кодировке Windows-1251
Библиотека для прямого и обратного преобразования символов юникода и символов кодировки
Windows-1251.
Особенностями библиотеки, по сравнению с библиотекой «golang.org/x/text/encoding/charmap», являются:
- простота и отсутствие зависимостей;
- лучшая производительность (за счет сфокусированности на Windows 1251 и простоте);
- взаимно однозначное преобразование данных для Windows-1251 (пояснение ниже).
Реализованные преобразования данных из Windows-1251 в Unicode и обратно являются взаимно
однозначными для набора символов Windows-1251. Символ 0x98
, несуществующий в кодировке
Windows-1251, отображается в символ юникода 0xfffd
(см. Replacement Character).
Преобразования произвольных данных Unicode в Windows-1251 и обратно не являются взаимно однозначными
и отсутствующие символы и символ юникода 0xfffd
отображаются в символ 0x98
, несуществующий в
кодировке Windows-1251.
Типовой пример использования функций библиотеки:
import "github.com/gelsrc/go-charset" ... uni := "Привет, мир!" // Преобразование Unicode в Windows-1251 (тип []byte) win := charset.Cp1251RunesToBytes([]rune(uni)) ... // Преобразование Windows-1251 (тип []byte) в Unicode uni = string(charset.Cp1251BytesToRunes(win))
при использовании файла зависимостей go.mod
можно зафиксировать версию, как показано в примере
ниже:
module ...
go 1.13
...
require github.com/gelsrc/go-charset v1.0.0
...
Библиотека так же является примером теста производительности (benchmark), встроенного в Go. Тест
производительности можно запустить командой go test -bench .
, пример результата тестирования
приведен ниже:
goos: windows
goarch: amd64
pkg: github.com/gelsrc/go-charset
BenchmarkCp1251BytesToRunes-4 1412524 846 ns/op
BenchmarkCp1251RunesToBytes-4 1549269 674 ns/op
BenchmarkComplex1-4 800250 1395 ns/op
BenchmarkComplex2-4 131938 9090 ns/op
PASS
ok github.com/gelsrc/go-charset 6.635s
По сравнению с библиотекой «golang.org/x/text/encoding/charmap», производительность этой библиотеки
оказывается больше от 2 до 6 раз в зависимости от сценария использования.
Всегда нужно быть готовым к тому, что кодировка входных данных из разных источников может различаться. Конечно, большинство используют операционную систему Windows, но не только. Go по умолчанию предполагает, что строки в программах будут в кодировке UTF-8. Если это не так, тогда их требуется декодировать, чтобы в дальнейшем можно было с ними работать. В данной инструкции показано, как читать и записывать файлы в других кодировках, помимо UTF-8.
Как использовать разные кодировками в Golang?
1. Создайте файл charset.go
со следующим содержимым:
Премиум 👑 канал по Golang
Рекомендуем вам супер TELEGRAM канал по Golang где собраны все материалы для качественного изучения языка. Удивите всех своими знаниями на собеседовании! 😎
Подписаться на канал
Уроки, статьи и Видео
Мы публикуем в паблике ВК и Telegram качественные обучающие материалы для быстрого изучения Go. Подпишитесь на нас в ВК и в Telegram. Поддержите сообщество Go программистов.
Go в ВК
ЧАТ в Telegram
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
package main import ( «fmt» «io/ioutil» «os» «golang.org/x/text/encoding/charmap» ) func main() { // Запись строки в кодировке Windows-1252 encoder := charmap.Windows1252.NewEncoder() s, e := encoder.String(«This is sample text with runes Š») if e != nil { panic(e) } ioutil.WriteFile(«example.txt», []byte(s), os.ModePerm) // Декодировка в UTF-8 f, e := os.Open(«example.txt») if e != nil { panic(e) } defer f.Close() decoder := charmap.Windows1252.NewDecoder() reader := decoder.Reader(f) b, err := ioutil.ReadAll(reader) if err != nil { panic(err) } fmt.Println(string(b)) } |
2. Запустите код через go run charset.go
;
3. Посмотрите на результат в терминале:
This is sample text with runes Š |
Конвертирование кодировки Windows-1251 в UTF-8
Пакет golang.org/x/text/encoding/charmap
содержит константы типа указателя Charmap
, что представляют наиболее часто используемые кодировки. Тип Charmap
предоставляет методы для создания кодера и декодера для определенного набора символов. Encoder
создает Writer
для кодировки, что кодирует записанные байты в выбранную кодировку. Также Decoder
может создать Reader
для декодировки, что декодирует все данные для чтения из выбранной кодировки.
Также можете ознакомиться с инструкцией для изменения кодировки строки, символы которой не относятся к Unicode.
Администрирую данный сайт с целью распространения как можно большего объема обучающего материала для языка программирования Go. В IT с 2008 года, с тех пор изучаю и применяю интересующие меня технологии. Проявляю огромный интерес к машинному обучению и анализу данных.
E-mail: vasile.buldumac@ati.utm.md
Образование
Технический Университет Молдовы (utm.md), Факультет Вычислительной Техники, Информатики и Микроэлектроники
- 2014 — 2018 Universitatea Tehnică a Moldovei, ИТ-Инженер. Тема дипломной работы «Автоматизация покупки и продажи криптовалюты используя технический анализ»
- 2018 — 2020 Universitatea Tehnică a Moldovei, Магистр, Магистерская диссертация «Идентификация человека в киберпространстве по фотографии лица»
- Variables
- func ANY_to_UTF8(src []byte, charset string) ([]byte, error)
- func CP1250_to_UTF8(src []byte) []byte
- func CP1251_to_UTF8(src []byte) []byte
- func CP1252_to_UTF8(src []byte) []byte
- func CP852_to_UTF8(src []byte) []byte
- func CP855_to_UTF8(src []byte) []byte
- func CP866_to_UTF8(src []byte) []byte
- func ISO88595_to_UTF8(src []byte) []byte
- func KOI8R_to_UTF8(src []byte) []byte
- func KOI8U_to_UTF8(src []byte) []byte
- func ToUTF8(table *DecodeTable, src []byte) []byte
- type DecodeTable
This section is empty.
View Source
var KnownCharsets = map[string](*DecodeTable){
"CP1250": &CP1250_UTF8_TABLE,
"cp1250": &CP1250_UTF8_TABLE,
"WINDOWS-1250": &CP1250_UTF8_TABLE,
"windows-1250": &CP1250_UTF8_TABLE,
"CP1251": &CP1251_UTF8_TABLE,
"cp1251": &CP1251_UTF8_TABLE,
"WINDOWS-1251": &CP1251_UTF8_TABLE,
"windows-1251": &CP1251_UTF8_TABLE,
"CP1252": &CP1252_UTF8_TABLE,
"cp1252": &CP1252_UTF8_TABLE,
"WINDOWS-1252": &CP1252_UTF8_TABLE,
"windows-1252": &CP1252_UTF8_TABLE,
"CP852": &CP852_UTF8_TABLE,
"cp852": &CP852_UTF8_TABLE,
"IBM852": &CP852_UTF8_TABLE,
"ibm852": &CP852_UTF8_TABLE,
"CP855": &CP855_UTF8_TABLE,
"cp855": &CP855_UTF8_TABLE,
"IBM855": &CP855_UTF8_TABLE,
"ibm855": &CP855_UTF8_TABLE,
"CP866": &CP866_UTF8_TABLE,
"cp866": &CP866_UTF8_TABLE,
"IBM866": &CP866_UTF8_TABLE,
"ibm866": &CP866_UTF8_TABLE,
"KOI8-R": &KOI8R_UTF8_TABLE,
"KOI8R": &KOI8R_UTF8_TABLE,
"koi8-r": &KOI8R_UTF8_TABLE,
"koi8r": &KOI8R_UTF8_TABLE,
"KOI8-U": &KOI8U_UTF8_TABLE,
"KOI8U": &KOI8U_UTF8_TABLE,
"koi8-u": &KOI8U_UTF8_TABLE,
"koi8u": &KOI8U_UTF8_TABLE,
"ISO-8859-5": &ISO88595_UTF8_TABLE,
"ISO8859-5": &ISO88595_UTF8_TABLE,
"iso-8859-5": &ISO88595_UTF8_TABLE,
"iso8859-5": &ISO88595_UTF8_TABLE,
}
func ISO88595_to_UTF8(src []byte) []byte
Все программисты сталкивались с проблемами кодировки при создании программ. Некоторые языки программирования, такие как Go, имеют свои особенности, которые могут быть причиной возникновения ошибок и нештатных ситуаций, если не учитывать их при написании кода. В этой статье мы рассмотрим проблемы, которые могут возникнуть при работе с кодировкой в Go и способы их решения.
Перекодирование в Go
Go предоставляет отличную поддержку UTF-8, который является стандартным форматом кодировки для многих языков. Однако, в процессе разработки приложений на Go, вам, возможно, придется столкнуться с проблемой перекодировки.
Проблема заключается в том, что Go не обеспечивает встроенной поддержки для других форматов кодировки, таких как ISO-8859-1 или Windows-1252, что может вызвать необходимость перекодирования данных.
Как перекодировать данные в Go?
Перекодирование данных в Go может быть выполнено с помощью средств, предоставляемых пакетом «golang.org/x/text/encoding». Этот пакет предоставляет поддержку нескольких форматов кодировки и предоставляет удобный API для их использования.
Например, чтобы преобразовать строку из одной кодировки в другую, вы можете использовать следующий код:
package main import ( "fmt" "golang.org/x/text/encoding" "golang.org/x/text/encoding/charmap" ) func main() { input := "Привет, мир!" // строка в кодировке UTF-8 charset := "windows-1251" // кодировка, в которую нужно перекодировать строку dec := charmap.Windows1251.NewDecoder() if out, err := dec.String(input); err == nil { fmt.Println("Исходная строка:", input) fmt.Println("Перекодированная строка в", charset, "кодировку:", out) } else { fmt.Println(err) } }
В этом примере мы используем пакет «golang.org/x/text/encoding/charmap», чтобы создать декодировщик Windows-1251, в которой мы хотим перекодировать исходную строку. Затем мы применяем метод «String» к декодировщику, чтобы перекодировать строку в требуемую кодировку.
Более сложные примеры перекодировки могут включать работу с различными форматами данных, такими как бинарные файлы или файлы JSON. Однако, в основном, использование пакета «golang.org/x/text/encoding» будет достаточно для выполнения перекодировки в Go.
Проблемы, связанные с кодировкой в Go
Следующие проблемы связанные с кодировкой в Go могут возникнуть при разработке приложений:
1. Некорректное отображение символов на экране
Эта проблема может возникнуть, если вы используете неправильную кодировку при выводе текста на экран. Например, если вы используете Windows-1252, а ваш терминал настроен на отображение в UTF-8, то некоторые символы будут отображаться неправильно.
Решение этой проблемы заключается в том, чтобы использовать правильную кодировку в своем коде, которая совпадает с кодировкой, заданной для вашего терминала.
2. Проблемы с чтением и записью файлов
Если вы используете неправильную кодировку при чтении или записи файлов на диске, то данные могут быть некорректно интерпретированы. Например, если файл в кодировке ISO-8859-1, а ваша программа пытается прочитать его как UTF-8, то некоторые символы могут отображаться неправильно.
Решение этой проблемы заключается в том, чтобы использовать правильную кодировку при чтении или записи файлов. Вы можете использовать пакет «golang.org/x/text/encoding» для выполнения перекодировки, если необходимо.
3. Проблемы при работе с внешними API
Некоторые внешние API могут предоставлять данные в других форматах кодировки, которые не поддерживаются Go. Например, если веб-сервер предоставляет данные в кодировке Shift-JIS, вы можете столкнуться с проблемой, если ваша программа ожидает данные в UTF-8.
Решение этой проблемы заключается в том, чтобы использовать пакеты, которые поддерживают нужную вам кодировку. Например, если вы работаете с веб-сервером, который предоставляет данные в Shift-JIS, вы можете использовать пакеты, такие как «golang.org/x/text/encoding/japanese» для выполнения перекодировки.
Заключение
Кодировка является важным аспектом при разработке приложений на Go. В этой статье мы рассмотрели проблемы, которые могут возникнуть при работе с кодировкой в Go, а также предоставили вам средства для их решения. Помните, что правильное использование кодировки позволяет убедиться в правильной интерпретации данных и создать более стабильные и надежные приложения.
#xml #golang #utf_8 #xmlparser #cp1251
Пишу парсер для xml файлов, но проблема в том, что в файле кодировка: encoding="windows-1251". Когда перевел кодировку в ut8 то следующем кодом смог распарсить документ. for _, file := range files { _, filename := utils.Unzip("/Users/farex/upload/"+file.Filename, "/Users/farex/upload/") _ = filename ///---------- Open our xmlFile----------------------- for _, file := range filename { xmlFile, err := os.Open("/Users/farex/upload/" + file) // if we os.Open returns an error then handle it if err != nil { fmt.Println(err) } fmt.Println("Successfully Opened " + file) if utils.Cut(file, 1) == "H" { defer xmlFile.Close() byteValue, _ := ioutil.ReadAll(xmlFile) var zl_list models.ZL_LIST xml.Unmarshal(byteValue, &zl_list) fmt.Println("---ZGLV---") fmt.Println("VERSION" + zl_list.ZGLV[0].VERSION) fmt.Println("DATA" + zl_list.ZGLV[0].DATA) fmt.Println("FILENAME" + zl_list.ZGLV[0].FILENAME) fmt.Println("SD_z" + zl_list.ZGLV[0].SD_Z) Это все работает, но задача парсить не Документы в формате utf8 , а в cp-1251. Как можно "конвертировать" cp-1251 в utf-8 ? Добавил меторд: func EncodeWindows1251(ba []uint8) []uint8 { enc := charmap.Windows1251.NewEncoder() out, _ := enc.String(string(ba)) return []uint8(out) } и соответственно вызываю его: byteValue, _ := ioutil.ReadAll(xmlFile) a := EncodeWindows1251(byteValue) var zl_list models.ZL_LIST xml.Unmarshal(a, &zl_list) Тоже не работает... Но если из документа убрать строку . То все работает и документ парсится... Неужели придется регуляркой удалять эту строчку в документе? Добавил метод наисанный ниже и за импортировал. "golang.org/x/text/encoding/charmap". Но: Образец файла xml тут кодировка cp-1251
Ответы
Ответ 1
Для этого существует поле Decoder.CharsetReader: // CharsetReader, if non-nil, defines a function to generate // charset-conversion readers, converting from the provided // non-UTF-8 charset into UTF-8. If CharsetReader is nil or // returns an error, parsing stops with an error. One of the // the CharsetReader's result values must be non-nil. CharsetReader func(charset string, input io.Reader) (io.Reader, error) Использовать можно так: d := xml.NewDecoder(xmlFile) d.CharsetReader = func(charset string, input io.Reader) (io.Reader, error) { switch charset { case "windows-1251": return charmap.Windows1251.NewDecoder().Reader(input), nil default: return nil, fmt.Errorf("unknown charset: %s", charset) } } err := d.Decode(&zlList)