zoukankan      html  css  js  c++  java
  • Golang utf8编码与utf16编码相互转换(string 和 []uint16互转)

    • 源代码已提交至 https://github.com/lianggx6/goutf16 ,可方便在代码中引用。
    • 最近使用Golang进行一些编码方面的工作,需要把utf8编码的string转化为utf16编码的uint16数组。
    • 比较简单直接的做法是借助golang中的utf16标准库和rune类型进行转换。如下所示。这个方法虽然写起来简单,但是缺点在于内存消耗更大,效率太低。主要原因在于string类型转换[]rune类型时,需要申请一次内存。[]rune再转换成[]uint16时又需要申请一遍内存。这样一来,这个操作就慢了很多。
    package main
    
    import (
    	"fmt"
    	"unicode/utf16"
    )
    
    func main() {
    	encodeContent := utf16.Encode([]rune("你好"))		//encode
    	fmt.Println(encodeContent)
    	decodeContent := utf16.Decode(encodeContent)		//decode
    	fmt.Println(string(decodeContent))
    }
    
    • 在网上找了许久也没有找到其他可以将一个utf8编码的数组转换为utf16编码的[]uint16数组的好方法,于是决定仿照utf16标准库自己动手实现一个。
    • 这份代码能够实现主要是在于,golang中,使用for range 语法迭代string和[]rune数组时,所得到的值是一样的。(但是使用len+下标访问就是不一样的了),所以完全可以把标准库中的代码抄过来改一下变量来实现。
    • 源码:
    package goutf16
    
    import (
    	"strings"
    	"unicode/utf16"
    	"unicode/utf8"
    )
    
    const (
    	replacementChar = 'uFFFD'     // Unicode replacement character
    	maxRune         = 'U0010FFFF' // Maximum valid Unicode code point.
    )
    
    const (
    	// 0xd800-0xdc00 encodes the high 10 bits of a pair.
    	// 0xdc00-0xe000 encodes the low 10 bits of a pair.
    	// the value is those 20 bits plus 0x10000.
    	surr1 = 0xd800
    	surr2 = 0xdc00
    	surr3 = 0xe000
    
    	surrSelf = 0x10000
    )
    
    func EncodeStringToUTF16(s string) []uint16 {
    	n := 0
    	for _, v := range s {
    		n++
    		if v >= 0x10000 {
    			n++
    		}
    	}
    
    	a := make([]uint16, n)
    	n = 0
    	for _, v := range s {
    		switch {
    		case 0 <= v && v < surr1, surr3 <= v && v < surrSelf:
    			// normal rune
    			a[n] = uint16(v)
    			n++
    		case surrSelf <= v && v <= maxRune:
    			// needs surrogate sequence
    			r1, r2 := utf16.EncodeRune(v)
    			a[n] = uint16(r1)
    			a[n+1] = uint16(r2)
    			n += 2
    		}
    	}
    	return a[:n]
    }
    
    func DecodeUTF16ToString(s []uint16) string {
    	n := 0
    	for i := 0; i < len(s); i++ {
    		switch r := s[i]; {
    		case r < surr1, surr3 <= r:
    			// normal rune
    			n += utf8.RuneLen(rune(r))
    		case surr1 <= r && r < surr2 && i+1 < len(s) &&
    			surr2 <= s[i+1] && s[i+1] < surr3:
    			// valid surrogate sequence
    			n += utf8.RuneLen(utf16.DecodeRune(rune(r), rune(s[i+1])))
    			i++
    		default:
    			// invalid surrogate sequence
    			n += utf8.RuneLen(replacementChar)
    		}
    	}
    	var b strings.Builder
    	b.Grow(n)
    	for i := 0; i < len(s); i++ {
    		switch r := s[i]; {
    		case r < surr1, surr3 <= r:
    			// normal rune
    			b.WriteRune(rune(r))
    		case surr1 <= r && r < surr2 && i+1 < len(s) &&
    			surr2 <= s[i+1] && s[i+1] < surr3:
    			// valid surrogate sequence
    			b.WriteRune(utf16.DecodeRune(rune(r), rune(s[i+1])))
    			i++
    		default:
    			// invalid surrogate sequence
    			b.WriteRune(replacementChar)
    		}
    	}
    	return b.String()
    }
    
    package main
    
    import (
    	"fmt"
    	"github.com/lianggx6/goutf16"
    )
    
    func main() {
    	encodeContent := goutf16.EncodeStringToUTF16("你好") //encode
    	fmt.Println(encodeContent)
    	decodeContent := goutf16.DecodeUTF16ToString(encodeContent)		//decode
    	fmt.Println(string(decodeContent))
    }
    
    • 由于这种实现,避免了转码过程中[]rune类型和string类型的转换,大大提高了转码效率,本质上和string转换为[]rune的消耗相差无几。
  • 相关阅读:
    吴恩达机器学习16:多变量线性回归(特征值以及多项式回归)
    吴恩达机器学习15:多变量线性回归(梯度下降运算中的实用技巧)
    吴恩达机器学习14:梯度下降以及平方差代价函数
    吴恩达机器学习13:多变量线性回归(使用梯度下降来求解多变量)
    吴恩达机器学习11:线性回归和多变量
    用通俗易懂的大白话讲解Map/Reduce原理
    漫画揭秘Hadoop MapReduce | 轻松理解大数据
    Pom.xml详解
    maven详细配置
    配置hadoop-eclipse-plugin(版本hadoop2.7.3):
  • 原文地址:https://www.cnblogs.com/lianggx6/p/12714797.html
Copyright © 2011-2022 走看看