Всегда нужно быть готовым к тому, что кодировка входных данных из разных источников может различаться. Конечно, большинство используют операционную систему 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, Магистр, Магистерская диссертация «Идентификация человека в киберпространстве по фотографии лица»
Преобразование кодировок
До этого момента мы работали с файлами в кодировке UTF-8. Однако файлы могут быть в различных кодировках. Например, в русской версии Windows файлы чаще всего сохранены в кодировке windows-1251. Чтобы иметь возможность выполнять преобразование кодировок нужно установить дополнительный пакет. Переходим в проект C:bookpackages
и выполняем следующую команду:
C:bookpackages>go get -u golang.org/x/text
go get: added golang.org/x/text v0.3.7
Обратите внимание на содержимое файла go.mod
, там появилась зависимость:
module exanple.com/mymodule
go 1.17
require golang.org/x/text v0.3.7 // indirect
Русские кодировки
Подключение пакета, предназначенного для преобразования кодировок, выглядит так:
import "golang.org/x/text/encoding/charmap"
Пакет содержит следующие основные объекты русских кодировок (полный список смотрите в документации):
var charmap.Windows1251 *charmap.Charmap
var charmap.CodePage866 *charmap.Charmap
var charmap.KOI8R *charmap.Charmap
Структура Charmap
содержит два основных метода:
(*charmap.Charmap).NewEncoder() *encoding.Encoder
(*charmap.Charmap).NewDecoder() *encoding.Decoder
С помощью структуры Encoder
выполняется преобразование данных из кодировки UTF-8 в кодировку объекта структуры Charmap
. Структура Encoder
содержит следующие методы:
String()
— выполняет преобразование кодировки строки. Формат метода:
(*encoding.Encoder).String(s string) (string, error)
Метод возвращает два значения. Через первое значение доступна преобразованная строка. Через второе значение доступен объект ошибки или nil
, если операция выполнена успешно. Пример преобразования строки в кодировке UTF-8 в строку в кодировке windows-1251:
// import "golang.org/x/text/encoding/charmap"
utf8 := "строка"
encoder := charmap.Windows1251.NewEncoder()
win1251, err := encoder.String(utf8)
if err != nil {
fmt.Println(err)
return
}
fmt.Println([]byte(win1251)) // [241 242 240 238 234 224]
Bytes()
— выполняет преобразование кодировки байтового слайса. Формат метода:
(*encoding.Encoder).Bytes(b []byte) ([]byte, error)
Метод возвращает два значения. Через первое значение доступен преобразованный байтовый слайс. Через второе значение доступен объект ошибки или nil
, если операция выполнена успешно. Пример:
utf8 := []byte("строка")
encoder := charmap.Windows1251.NewEncoder()
win1251, err := encoder.Bytes(utf8)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(win1251) // [241 242 240 238 234 224]
Writer()
— возвращает объектio.Writer
с помощью которого можно записывать преобразованные данные в поток вывода. Формат метода:
(*encoding.Encoder).Writer(w io.Writer) io.Writer
Пример записи строки в файл в кодировке windows-1251:
func test() {
file, err := os.Create(`C:booktest.txt`)
if err != nil {
fmt.Println(err)
return
}
defer file.Close()
encoder := charmap.Windows1251.NewEncoder()
win1251 := encoder.Writer(file)
_, err = io.WriteString(win1251, "Строка1nСтрока2")
if err != nil {
fmt.Println(err)
return
}
fmt.Println("Операция выполнена успешно")
}
С помощью структуры Decoder
выполняется преобразование данных из кодировки объекта структуры Charmap
в кодировку UTF-8. Структура Decoder
содержит следующие методы:
String()
— выполняет преобразование кодировки строки. Формат метода:
(*encoding.Decoder).String(s string) (string, error)
Метод возвращает два значения. Через первое значение доступна преобразованная строка. Через второе значение доступен объект ошибки или nil
, если операция выполнена успешно. Пример преобразования строки в кодировке windows-1251 в строку в кодировке UTF-8:
// import "golang.org/x/text/encoding/charmap"
win1251 := "xf1xf2xf0xeexeaxe0"
decoder := charmap.Windows1251.NewDecoder()
utf8, err := decoder.String(win1251)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(utf8) // строка
Bytes()
— выполняет преобразование кодировки байтового слайса. Формат метода:
(*encoding.Decoder).Bytes(b []byte) ([]byte, error)
Метод возвращает два значения. Через первое значение доступен преобразованный байтовый слайс. Через второе значение доступен объект ошибки или nil
, если операция выполнена успешно. Пример:
win1251 := []byte{241, 242, 240, 238, 234, 224}
decoder := charmap.Windows1251.NewDecoder()
utf8, err := decoder.Bytes(win1251)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(utf8)) // строка
Reader()
— возвращает объектio.Reader
с помощью которого можно считывать преобразованные данные из потока ввода. Формат метода:
(*encoding.Decoder).Reader(r io.Reader) io.Reader
Пример чтения из файла, сохраненного в кодировке windows-1251:
func test() {
file, err := os.Open(`C:booktest.txt`)
if err != nil {
fmt.Println(err)
return
}
defer file.Close()
decoder := charmap.Windows1251.NewDecoder()
win1251 := decoder.Reader(file)
utf8, err := io.ReadAll(win1251)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(utf8))
}
Кодировка UTF-16
Для работы с кодировкой UTF-16 нужно использовать функцию UTF16()
из пакета golang.org/x/text/encoding/unicode
. Формат функции:
unicode.UTF16(e unicode.Endianness,
b unicode.BOMPolicy) encoding.Encoding
Первый параметр задает порядок следования байтов. Можно указать константы unicode.LittleEndian
или unicode.BigEndian
. Второй параметр задает политику обработки метки порядка байтов (BOM). Можно указать следующие константы:
unicode.UseBOM
— метка порядка байтов используется;unicode.IgnoreBOM
— метка порядка байтов игнорируется;unicode.ExpectBOM
— метка порядка байтов используется для переопределения кодировки по умолчанию.
Функция UTF16()
возвращает объект Encoding
, который содержит знакомые уже нам методы:
(encoding.Encoding).NewEncoder() *encoding.Encoder
(encoding.Encoding).NewDecoder() *encoding.Decoder
Пример преобразования строки в кодировке UTF-8 в строку в кодировке UTF-16LE с BOM:
// import "golang.org/x/text/encoding/unicode"
utf8 := "строка"
encoder := unicode.UTF16(unicode.LittleEndian,
unicode.UseBOM).NewEncoder()
utf16le, err := encoder.String(utf8)
if err != nil {
fmt.Println(err)
return
}
fmt.Println([]byte(utf16le))
// [255 254 65 4 66 4 64 4 62 4 58 4 48 4]
Пример преобразования строки в кодировке UTF-16LE в строку в кодировке UTF-8:
utf16le := "xffxfeAx04Bx04@x04>x04:x040x04"
decoder := unicode.UTF16(unicode.LittleEndian,
unicode.UseBOM).NewDecoder()
utf8, err := decoder.String(utf16le)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(utf8) // строка
Кодировка UTF-32
Для работы с кодировкой UTF-32 нужно использовать функцию UTF32()
из пакета golang.org/x/text/encoding/unicode/utf32
. Формат функции:
utf32.UTF32(e utf32.Endianness, b utf32.BOMPolicy) encoding.Encoding
Первый параметр задает порядок следования байтов. Можно указать константы utf32.LittleEndian
или utf32.BigEndian
. Второй параметр задает политику обработки метки порядка байтов (BOM). Можно указать следующие константы:
utf32.UseBOM
— метка порядка байтов используется;utf32.IgnoreBOM
— метка порядка байтов игнорируется;utf32.ExpectBOM
— метка порядка байтов используется для переопределения кодировки по умолчанию.
Функция UTF32()
возвращает объект Encoding
, который содержит знакомые уже нам методы:
(encoding.Encoding).NewEncoder() *encoding.Encoder
(encoding.Encoding).NewDecoder() *encoding.Decoder
Пример преобразования строки в кодировке UTF-8 в строку в кодировке UTF-32LE с BOM:
// import "golang.org/x/text/encoding/unicode/utf32"
utf8 := "тест"
encoder := utf32.UTF32(utf32.LittleEndian,
utf32.UseBOM).NewEncoder()
utf32le, err := encoder.String(utf8)
if err != nil {
fmt.Println(err)
return
}
fmt.Println([]byte(utf32le))
// [255 254 0 0 66 4 0 0 53 4 0 0 65 4 0 0 66 4 0 0]
Пример преобразования строки в кодировке UTF-32LE в строку в кодировке UTF-8:
utf32le := "xffxfex00x00Bx04x00x005x04x00x00Ax04" +
"x00x00Bx04x00x00"
decoder := utf32.UTF32(utf32.LittleEndian,
utf32.UseBOM).NewDecoder()
utf8, err := decoder.String(utf32le)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(utf8) // тест
Учебник Go (Golang) в формате PDF
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
«fmt» | |
«golang.org/x/text/encoding/charmap» | |
) | |
func main() { | |
for i := 0; i <= 255; i++ { | |
charnum := uint8(i) | |
orig := []uint8{charnum} | |
utf8 := DecodeWindows1251(orig) | |
win1251 := EncodeWindows1251(utf8) | |
if string(orig) != string(win1251) { | |
fmt.Printf(«Oh~.. Failed at charnum 0x%xn«, i) | |
fmt.Printf(«(orig, utf8, win1251)n«) | |
fmt.Printf(«string: %s, %s, %sn«, string(orig), string(utf8), string(win1251)) | |
fmt.Printf(«quoted: %+q, %+q, %+qn«, string(orig), string(utf8), string(win1251)) | |
fmt.Printf(«hex : % x, % x, % xn«, string(orig), string(utf8), string(win1251)) | |
} | |
} | |
} | |
func DecodeWindows1251(ba []uint8) []uint8 { | |
dec := charmap.Windows1251.NewDecoder() | |
out, _ := dec.Bytes(ba) | |
return out | |
} | |
func EncodeWindows1251(ba []uint8) []uint8 { | |
enc := charmap.Windows1251.NewEncoder() | |
out, _ := enc.String(string(ba)) | |
return []uint8(out) | |
} |
I checked out the docs, here, and I came up with a way to convert an array of bytes to (or from) UTF-8.
What I have a hard time with is that, so far, I’ve not found an interface that would allow me to use a locale. Instead, it’s like the possible ways are limited to predefined sets of encodings.
In my case, I needed to convert UTF-16 (really I have USC-2 data, but it should still work) to UTF-8. To do that, I needed to check for the BOM and then do the conversion:
bom := buf[0] + buf[1] * 256
if bom == 0xFEFF {
enc = unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM)
} else if bom == 0xFFFE {
enc = unicode.UTF16(unicode.BigEndian, unicode.IgnoreBOM)
} else {
return Error("BOM missing")
}
e := enc.NewDecoder()
// convert USC-2 (LE or BE) to UTF-8
utf8 := e.Bytes(buf[2:])
Unfortunate that I have to use «ignore» BOM since in my case it should instead be forbidden past the first character. But that’s close enough for my situation. These functions were mentioned in a couple of places, but not shown in practice.
- 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
Пишу парсер для 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)
Тоже не работает…
Но если из документа убрать строку <?xml version="1.0" encoding="windows-1251"?>
.
То все работает и документ парсится… Неужели придется регуляркой удалять эту строчку в документе?
Добавил метод наисанный ниже и за импортировал. «golang.org/x/text/encoding/charmap».
Но:
Образец файла xml тут кодировка cp-1251
Mar 9 2016
At one point or another, every developer gets stuck converting a pile of files from one character encoding to another. Go’s native character set is UTF-8, and the core Go libraries don’t come with tools for converting character sets. However, one of the Go extension libraries makes this easy.
The package you want is golang.org/x/text, which comes with a variety of tools for working with text. And the one we’re most interested in is the encoding set of packages.
Decode to UTF-8, Encode to Something Else
The encoding
library defines Decoder
and Encoder
structs.
- The
Decoder
is used for starting with text in a non-UTF-8 character set, and transforming the source text to UTF-8 text. - The
Encoder
is used to take UTF-8 text and transform it to another encoding.
Particular encodings are stored in a number of subpackages beneath golang.org/x/text/encoding
.
One of the most widely used encodings in the North America and Europe is ISO-8859-1 (aka Latin-1). So here we’ll show how to decode from that format into UTF-8.
A number of common Western encodings are located in the golang.org/x/text/encoding/charmap package. This includes the ISO-8859 family as well as the Windows 1252 character set.
package main
import (
"io"
"os"
"golang.org/x/text/encoding/charmap"
)
func main() {
f, err := os.Open("my_isotext.txt")
if err != nil {
// handle file open error
}
out, err := os.Create("my_utf8.txt")
if err != nil {
// handler error
}
r := charmap.ISO8859_1.NewDecoder().Reader(f)
io.Copy(out, r)
out.Close()
f.Close()
}
The above opens a ISO-8859-1 source text (my_isotext.txt
), creates a destination file (my_utf.txt
), and copies the first to the second. But to decode from ISO-8859-1 to UTF-8, we wrap the original file reader (f
) with a decoder:
r := charmap.ISO8859_1.NewDecoder().Reader(f)
Decoding happens as we stream data from the source file to the destination.
From the command line, we can see the result:
⇒ go run main.go
⇒ file my_isotext.txt
my_isotext.txt: ISO-8859 English text, with CRLF line terminators
⇒ file my_utf8.txt
my_utf8.txt: UTF-8 Unicode English text, with CRLF line terminators
Decoders and encoders can also work with string
s and []byte
, making them versatile whatever your encoding needs are.
- go
- golang
- goquickly
- gohack
In this blog, we will learn about the Golang UTF8 Package and Character Encoding in Programming Languages.
The Golang Unicode/utf8 package provides several useful functions for querying and manipulating strings and []bytes which hold UTF8 bytes.
First of all, let’s understand the difference between UTF8 and ASCII Encoding.
ASCII vs UTF8 Encoding
In earlier days of the invention of programming language, the computer scientists felt the need for only 128 characters and thus they encoded the 128 characters in 1 byte (primarily 7 bits, as the starting 1 bit is only for signal).
2^7 = 128
This Encoding was called ASCII (American Standard Code for Information Interchange).
ASCII Example:
A (Capital) has an ASCII value of 65 – Binary representation of A is: 1000001
01000001
while nowadays, we use a lot of characters and many countries type code in their own native language other than English than how it’s possible.
Unicode is a standard that encodes almost all the characters used in the world for convenience purposes. The UTF8 (8-bit Unicode Transformation Format) defined by Unicode Standards, is a character encoding that encodes a total of 1,112,064 characters.
The UTF8 is developed by Ken Thompson and Rob Pike (also developers of The GO Programming language). This is also the reason why Golang is typed in UTF8 Encoding.
UTF8 is a variable width character encoding, and uses one – four bytes to encode a character. UTF8 Supports ASCII as it is backward compatible. As ASCII Characters take only 7 bits or 1 byte to encode a character, it is given first place in the UTF8 Encoding.
Other Characters take two four bytes in order to encode.
The Characters take two or more bytes for UTF8 encoding, there is a similarity, the first bit is preceded by as many ones as the characters encoding size and a Zero. Example.
Byte1 = 110xxxxx
After that, all the bytes get preceded by 10s.
Byte2 = 10xxxxxx
Visit the Wikipedia page to know more about UTF8 Encoding.
Devanagari (Hindi) UTF8 Code
In this blog, I will be using examples in Hindi as well as English Unicodes, Take a reference for Devanagri UTF8 Code.
Golang UTF8 Package DecodeRune
func DecodeRune(p []byte) (r rune, size int)
Decode Rune takes the first UTF8 encoding from the passed string and returns rune of the encoded character and the size it takes in UTF8 encoding.
If the passed string is empty, the DecodeRune function returns rune error and 0 as the size of the encoded character. If the encoded string is invalid then the function returns rune error and 1.
package main
import (
"fmt"
"unicode/utf8"
)
func main() {
str := []byte("नमस्ते दुनिया") // Hello World in Hindi
for len(b) > 0 {
r, size := utf8.DecodeRune(str)
fmt.Printf("%c %v bytesn", r, size)
str = str[size:]
}
}
Output:
न 3 bytes
म 3 bytes
स 3 bytes
् 3 bytes
त 3 bytes
े 3 bytes
1 bytes
द 3 bytes
ु 3 bytes
न 3 bytes
ि 3 bytes
य 3 bytes
ा 3 bytes
DecodeRuneInString
func DecodeRuneInString(s string) (r rune, size int)
Golang UTF8 Package DecodeRuneInString function is like DecodeRune but its input is a string.
Golang UTF8 Package DecodeLastRune
func DecodeLastRune(p []byte) (r rune, size int)
Golang UTF8 Package DecodeLastRune function takes the last UTF8 encoding from the passed string, and returns rune of the encoded character and the size it takes in UTF8 encoding.
If the string is empty DecodeLastRune function returns (RuneError, 0).
Otherwise, if the encoding is invalid, the function returns (RuneError, 1).
package main
import (
"fmt"
"unicode/utf8"
)
func main() {
str := []byte("नमस्ते दुनिया") // Hello World in Hindi
for len(b) > 0 {
r, size := utf8.DecodeLastRune(str)
fmt.Printf("UTF8 Code: %v %c %v bytesn", r, r, size)
str = str[:len(str)-size]
}
}
UTF8 Code: 2366 ा 3 bytes
UTF8 Code: 2351 य 3 bytes
UTF8 Code: 2367 ि 3 bytes
UTF8 Code: 2344 न 3 bytes
UTF8 Code: 2369 ु 3 bytes
UTF8 Code: 2342 द 3 bytes
UTF8 Code: 32 1 bytes
UTF8 Code: 2375 े 3 bytes
UTF8 Code: 2340 त 3 bytes
UTF8 Code: 2381 ् 3 bytes
UTF8 Code: 2360 स 3 bytes
UTF8 Code: 2350 म 3 bytes
UTF8 Code: 2344 न 3 bytes
DecodeLastRuneInString
func DecodeLastRuneInString(s string) (r rune, size int)
Golang UTF8 Package DecodeLastRuneInString function is like DecodeLastRune but its input is a string.
Example:
str := "नमस्ते दुनिया" // Hello World in Hindi
for len(str) > 0 {
r, size := utf8.DecodeLastRuneInString(str)
fmt.Printf("UTF8 Code: %v %c %v bytesn", r, r, size)
str = str[:len(str)-size]
}
UTF8 Code: 2366 ा 3 bytes
UTF8 Code: 2351 य 3 bytes
UTF8 Code: 2367 ि 3 bytes
UTF8 Code: 2344 न 3 bytes
UTF8 Code: 2369 ु 3 bytes
UTF8 Code: 2342 द 3 bytes
UTF8 Code: 32 1 bytes
UTF8 Code: 2375 े 3 bytes
UTF8 Code: 2340 त 3 bytes
UTF8 Code: 2381 ् 3 bytes
UTF8 Code: 2360 स 3 bytes
UTF8 Code: 2350 म 3 bytes
UTF8 Code: 2344 न 3 bytes
Golang UTF8 Package EncodeRune
func EncodeRune(b []byte, r rune) int
The EncodeRune Function takes a byte array and a rune and encodes it to UTF8 Encoding.
Example:
package main
import (
"fmt"
"unicode/utf8"
)
func main() {
r := 'क' // English K
b := make([]byte, 3)
n := utf8.EncodeRune(b, r)
fmt.Print("Byte Array :",b)
fmt.Print("Number of Bytes Written:",n)
}
Output:
Byte Array : [224 164 149] Number of Bytes Written: 3
Explanation:
The Hindi letter ‘क‘ (DEVANAGARI LETTER KA) UTF8 encoding takes 3 bytes. The output returns the bytes of the letter. Let’s dive deeper into the binary and know how the letter is encoded in UTF8.
Binary of 224:
11100000
Binary of 164:
10100100
Binary of 149:
10010101
According to the UTF8 Encoding Rule, the first byte (except any ASCII Characters) is preceded by the number of ones equal to the size of that character and next 0, and the rest of the bytes will precede with 10s, this is a fixed rule for UTF8 Encoding.
Golang UTF8 RuneCount
func RuneCount(b []byte) int
Golang UTF8 RuneCount function returns the number of runes in an array of bytes.
Example:
func main() {
b := []byte("Hello, दुनिया") // World in Hindi
fmt.Println(b)
fmt.Println("bytes =", len(b))
fmt.Println("runes =", utf8.RuneCount(b))
}
Output:
[72 101 108 108 111 44 32 224 164 166 224 165 129 224 164 168 224 164 191 224 164 175 224 164 190]bytes = 25
runes = 13
In the output, the bytes array contains 25 elements but there are only a few when we look at it.
The byte array, from 72 to 32 it contains the “Hello,” String and after that contains the byte for UTF8 Encoded string.
The reason why the string splits into a long byte array as each character takes 3 bytes to encode.
Golang UTF8 RuneCountInString
func RuneCountInString(s string) (n int)
Golang UTF8 RuneCountInString function is like RuneCount but its input is a string.
Golang UTF8 Valid
func Valid(b []byte) bool
Golang UTF8 Valid function returns a boolean value true if the byte array consists entirely of valid UTF-8-encoded runes, else false.
func main() {
valid := []byte("Hello, दुनिया") // World in Hindi
invalid := []byte{0xff, 0xfe, 0xfd}
fmt.Println(utf8.Valid(valid))
fmt.Println(utf8.Valid(invalid))
}
Output:
true
false
ValidRune and ValidString work the same as the Valid function. The only difference is in the input section, the ValidRune take rune as input and the ValidString takes a string value as input.
Hope you like it!
Also, read Why Golang is called the future of Server-side language?
Learn more about Golang UTF8 Package from the official Documentation.