前言
比如 utf8
、gbk
、GB18030
。
excel和csv中有多种编码格式,也是比较头疼的。这里提供多种解析方式。开箱即用的工具
源码
// 转为utf8格式 ConvertToString("你的字符")
package utils import ( "github.com/axgle/mahonia" "golang.org/x/text/encoding/simplifiedchinese" ) const ( GBK string = "GBK" UTF8 string = "UTF8" UNKNOWN string = "UNKNOWN" ) func ConvertToStringByCode(src string, srcCode string, tagCode string) string { srcCoder := mahonia.NewDecoder(srcCode) srcResult := srcCoder.ConvertString(src) tagCoder := mahonia.NewDecoder(tagCode) _, cdata, _ := tagCoder.Translate([]byte(srcResult), true) result := string(cdata) return result } func ConvertToStringGbkToUtf8(src string) string { if isUtf8([]byte(src)) { return src } var srcCode = "gbk" var tagCode = "utf-8" srcCoder := mahonia.NewDecoder(srcCode) srcResult := srcCoder.ConvertString(src) tagCoder := mahonia.NewDecoder(tagCode) _, cdata, _ := tagCoder.Translate([]byte(srcResult), true) result := string(cdata) return result } func ConvertToString(src string) string { if isUtf8([]byte(src)) { return src } if isGBK([]byte(src)) { utf8Data, err := simplifiedchinese.GBK.NewDecoder().Bytes([]byte(src)) if err != nil { return src } if isUtf8(utf8Data) { return string(utf8Data) } else { return ConvertToStringGbkToUtf8(string(utf8Data)) } } sink, err := simplifiedchinese.GB18030.NewDecoder().Bytes([]byte(src)) if err != nil { return src } return string(sink) } func isGBK(data []byte) bool { length := len(data) var i int = 0 for i < length { if data[i] <= 0x7f { //编码0~127,只有一个字节的编码,兼容ASCII码 i++ continue } else { //大于127的使用双字节编码,落在gbk编码范围内的字符 if data[i] >= 0x81 && data[i] <= 0xfe && data[i+1] >= 0x40 && data[i+1] <= 0xfe && data[i+1] != 0xf7 { i += 2 continue } else { return false } } } return true } func preNUm(data byte) int { var mask byte = 0x80 var num int = 0 //8bit中首个0bit前有多少个1bits for i := 0; i < 8; i++ { if (data & mask) == mask { num++ mask = mask >> 1 } else { break } } return num } func isUtf8(data []byte) bool { i := 0 for i < len(data) { if (data[i] & 0x80) == 0x00 { // 0XXX_XXXX i++ continue } else if num := preNUm(data[i]); num > 2 { // 110X_XXXX 10XX_XXXX // 1110_XXXX 10XX_XXXX 10XX_XXXX // 1111_0XXX 10XX_XXXX 10XX_XXXX 10XX_XXXX // 1111_10XX 10XX_XXXX 10XX_XXXX 10XX_XXXX 10XX_XXXX // 1111_110X 10XX_XXXX 10XX_XXXX 10XX_XXXX 10XX_XXXX 10XX_XXXX // preNUm() 返回首个字节的8个bits中首个0bit前面1bit的个数,该数量也是该字符所使用的字节数 i++ for j := 0; j < num-1; j++ { //判断后面的 num - 1 个字节是不是都是10开头 if (data[i] & 0xc0) != 0x80 { return false } i++ } } else { //其他情况说明不是utf-8 return false } } return true } func GetStrCoding(data []byte) string { if isUtf8(data) == true { return UTF8 } else if isGBK(data) == true { return GBK } else { return UNKNOWN } }