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
}