go编码相关示例

1.BCD码和字符串互转

//字符串utf-8编码兼容ASCII
//案例:传输32010600019240,BCD码传输,转储字符串数字

//1.将32 01 06 00 01 92 40 BCD编码后[50 1 6 0 1 146 64]
src := "32010600019240"
data := hex.DecodeString(src)

//10进制显示: data = []byte{50, 1, 6, 0, 1, 146, 64}
//16进制显示: data = []byte{0x32, 0x01, 0x06, 0x00, 0x01, 0x92, 0x40}

//2.接收BCD码data
str := hex.EncodeToString(data)
fmt.Println(str)
//32010600019240

//总结:
//BCD码是用字面值相同的16进制表示10进制。例如传输十进制10,BCD编码后传输的是十六进制的10。
//hex包是十六进制编码包

2.BCD码和整形互转

//BCD转int 
//如传输 十进制100
//真正传输的是BCD编码[]byte{1,0},其底层二进制为1 0000 0000
//将其解码为100。

//(1)方便理解的转法,根据BCD码的本质可知: 底层传输的是 0x100,[]byte表示为[1,0],二进制表示为 1 00000000,所以先将[]byte转为整形=256,再将其转为16进制字符=100,最后将100的字面量转为整形。
func Bcd2Int(b []byte) int {
	n, _ := strconv.Atoi(fmt.Sprintf("%x", Bin2UInt(b)))
	return n
}
//(2)性能更好的转法
func BCD2Int(b []byte) int {
	var n int
	len := len(b)
	for i := 1; i <= len; i++ {
		temp := b[len-i]
		n += int(temp&0xF) * int(math.Pow10(i*2-2))
		n += int(temp&0xF0) * int(math.Pow10(i*2-1))
	}
	return n
}

//uint转BCD
func Uint2BCD(n uint64, isBigEndian bool) []byte {
	var b []byte
	if n < 256 {
		b = []byte{0}
	}
	for i := 0; ; i++ {
		h := (n / 10) % 10
		l := n % 10
		b = append(b, byte(h<<4|l))
		n = n / 100
		if n == 0 {
			break
		}
	}
	if !isBigEndian {
		return b
	}
	l := len(b)
	var r = make([]byte, l)
	for i, v := range b {
		r[l-1-i] = v
	}
	return r
}
//未考虑负数和整数类型最大容量

3.BIN码和无符号整形互转

//BIN码转无符号整形
func BIN2Uint64(bin []byte, order binary.ByteOrder) (uint64, error) {
	len := len(bin)
	switch len {
	case 1:
		return uint64(bin[0]), nil
	case 2:
		return uint64(order.Uint16(bin)), nil
	case 3, 4:
		bin4 := make([]byte, 8)
		copy(bin4[4-len:], bin) //前面字节填充0
		return uint64(order.Uint32(bin4)), nil
	case 5, 6, 7, 8:
		bin8 := make([]byte, 8)
		copy(bin8[8-len:], bin)
		return order.Uint64(bin8), nil
	default:
		return 0, errors.New("不符合字节长度范围1-8")
	}
}
//无符号整形转BIN码
var lengthErr = errors.New("需要更大的长度存储该数值")
func Uint2BIN(n uint64, len uint8, order binary.ByteOrder) ([]byte, error) {
	switch len {
	case 1:
		if n > math.MaxUint8 {
			return nil, lengthErr
		}
		return []byte{byte(n)}, nil
	case 2:
		if n > math.MaxUint16 {
			return nil, lengthErr
		}
		b := make([]byte, 2)
		order.PutUint16(b, uint16(n))
		return b, nil
	case 3, 4:
		if n > math.MaxUint32 {
			return nil, lengthErr
		}
		b := make([]byte, 4)
		order.PutUint32(b, uint32(n))
		return b, nil
	case 5, 6, 7, 8:
		if n > math.MaxUint64 {
			return nil, lengthErr
		}
		b := make([]byte, 8)
		order.PutUint64(b, n)
		return b, nil
	default:
		return nil, errors.New("非法字节长度")
	}
}

4.BIN码和浮点数互转

//浮点数扩大10的n次方至整数传输,n为小数点位数

//BIN转float64, n为小数位数
func Bin2Float64(b []byte, n int) float64 {
	f := float64(BIN2Uint64(b, binary.LittleEndian)) / math.Pow10(n)
	num, _ := strconv.ParseFloat(strconv.FormatFloat(f, 'f', bit, 64), 64)
	return num
}
//float64转BIN
func Float64ToBin(f float64, byteLength byte, n int) []byte {
	i := int64(f * math.Pow10(n))
	return Uint2BIN(i, byteLength, binary.LittleEndian)
}

5.CP56Time2a时间格式

// ParseCP56time2a 解析CP56time2a 为字符串时间
func ParseCP56time2a(b []byte) string {
	second := ((int64(b[1]) << 8) + int64(b[0])) / 1000
	min := b[2] & 0x3F
	hour := b[3] & 0x1F
	day := b[4] & 0x1F
	month := b[5] & 0xF
	year := b[6] & 0x7F
	return fmt.Sprintf("20%d-%02d-%02d %02d:%02d:%02d",
		year, month, day, hour, min, second)
}

// EncodeCP56time2a 字符串时间编码为CP56time2a格式
func EncodeCP56time2a(str string) []byte {
	var b = []byte{0, 0, 0, 0, 0, 0, 0}
	parse, err := time.Parse("2006-01-02 15:04:05", str)
	if err != nil {
		return b
	}
	second := Int2Bin(int64(parse.Second())*1000, 2, binary.LittleEndian)
	min := byte(parse.Minute())
	hour := byte(parse.Hour())
	day := byte(parse.Day())
	month := byte(parse.Month())
	year := byte(parse.Year() - 2000)
	b[0] = second[0]
	b[1] = second[1]
	b[2] = min
	b[3] = hour
	b[4] = day
	b[5] = month
	b[6] = year
	return b
}
posted @ 2023-10-25 21:04  longan55  阅读(177)  评论(0)    收藏  举报