diff --git a/g/encoding/gbinary/gbinary.go b/g/encoding/gbinary/gbinary.go index a4023268d..a6c11762c 100644 --- a/g/encoding/gbinary/gbinary.go +++ b/g/encoding/gbinary/gbinary.go @@ -16,11 +16,20 @@ import ( // 二进制位(0|1) type Bit uint8 -// 整形二进制打包,注意参数必须为字长确定的类型:int8/16/32/64、uint8/16/32/64 +// 针对基本类型进行二进制打包,支持的基本数据类型包括:int/8/16/32/64、uint/8/16/32/64、float32/64、bool、string、[]byte func Encode(vs ...interface{}) ([]byte, error) { buf := new(bytes.Buffer) for i := 0; i < len(vs); i++ { - err := binary.Write(buf, binary.LittleEndian, vs[i]) + var err error = nil + switch vs[i].(type) { + case int: buf.Write(EncodeInt(vs[i].(int))) + case uint: buf.Write(EncodeUint(vs[i].(uint))) + case bool: buf.Write(EncodeBool(vs[i].(bool))) + case string: buf.Write(EncodeString(vs[i].(string))) + case []byte: buf.Write(vs[i].([]byte)) + default: + err = binary.Write(buf, binary.LittleEndian, vs[i]) + } if err != nil { return nil, err } @@ -28,7 +37,8 @@ func Encode(vs ...interface{}) ([]byte, error) { return buf.Bytes(), nil } -// 整形二进制解包,注意第二个及其后参数为字长确定的整形变量的指针地址,字长确定的类型:int8/16/32/64、uint8/16/32/64 +// 整形二进制解包,注意第二个及其后参数为字长确定的整形变量的指针地址,以便确定解析的[]byte长度, +// 例如:int8/16/32/64、uint8/16/32/64、float32/64等等 func Decode(b []byte, vs ...interface{}) error { buf := bytes.NewBuffer(b) for i := 0; i < len(vs); i++ { @@ -48,6 +58,40 @@ func DecodeToString(b []byte) string { return string(b) } +func EncodeBool(b bool) []byte { + if b == true { + return []byte{1} + } else { + return []byte{0} + } +} + +// 自动识别int类型长度,转换为[]byte +func EncodeInt(i int) []byte { + if i <= math.MaxInt8 { + return EncodeInt8(int8(i)) + } else if i <= math.MaxInt16 { + return EncodeInt16(int16(i)) + } else if i <= math.MaxInt32 { + return EncodeInt32(int32(i)) + } else { + return EncodeInt64(int64(i)) + } +} + +// 自动识别uint类型长度,转换为[]byte +func EncodeUint(i uint) []byte { + if i <= math.MaxUint8 { + return EncodeUint8(uint8(i)) + } else if i <= math.MaxUint16 { + return EncodeUint16(uint16(i)) + } else if i <= math.MaxUint32 { + return EncodeUint32(uint32(i)) + } else { + return EncodeUint64(uint64(i)) + } +} + func EncodeInt8(i int8) []byte { return []byte{byte(i)} } @@ -116,6 +160,43 @@ func fillUpSize(b []byte, l int) []byte { return c } +// 将二进制解析为int类型,根据[]byte的长度进行自动转换 +func DecodeToInt(b []byte) int { + if len(b) < 2 { + return int(DecodeToInt8(b)) + } else if len(b) < 3 { + return int(DecodeToInt16(b)) + } else if len(b) < 5 { + return int(DecodeToInt32(b)) + } else { + return int(DecodeToInt64(b)) + } +} + +// 将二进制解析为uint类型,根据[]byte的长度进行自动转换 +func DecodeToUint(b []byte) uint { + if len(b) < 2 { + return uint(DecodeToUint8(b)) + } else if len(b) < 3 { + return uint(DecodeToUint16(b)) + } else if len(b) < 5 { + return uint(DecodeToUint32(b)) + } else { + return uint(DecodeToUint64(b)) + } +} + +// 将二进制解析为bool类型,识别标准是判断二进制中数值是否都为0,或者为空 +func DecodeToBool(b []byte) bool { + if len(b) == 0 { + return false + } + if bytes.Compare(b, make([]byte, len(b))) == 0 { + return false + } + return true +} + func DecodeToInt8(b []byte) int8 { return int8(b[0]) } diff --git a/geg/encoding/gbinary/binary.go b/geg/encoding/gbinary/binary.go index 08061753b..610a8e79f 100644 --- a/geg/encoding/gbinary/binary.go +++ b/geg/encoding/gbinary/binary.go @@ -1,33 +1,49 @@ package main import ( - "gitee.com/johng/gf/g/encoding/gbinary" - "gitee.com/johng/gf/g/os/glog" "fmt" + "gitee.com/johng/gf/g/os/glog" + "gitee.com/johng/gf/g/encoding/gbinary" ) func main() { - // 使用gbinary.Encoded对整形二进制打包,注意参数必须为字长确定的类型:int8/16/32/64、uint8/16/32/64 - if buffer, err := gbinary.Encode(int32(18), int64(24)); err != nil { + // 使用gbinary.Encoded对基本数据类型进行二进制打包 + if buffer, err := gbinary.Encode(18, 300, 1.01); err != nil { glog.Error(err) } else { fmt.Println(buffer) } - - // 使用gbinary.Decode对整形二进制解包,注意第二个及其后参数为字长确定的整形变量的指针地址,字长确定的类型:int8/16/32/64、uint8/16/32/64 - if buffer, err := gbinary.Encode(int32(18), int64(24)); err != nil { + // 使用gbinary.Decode对整形二进制解包,注意第二个及其后参数为字长确定的整形变量的指针地址,字长确定的类型, + // 例如:int8/16/32/64、uint8/16/32/64、float32/64 + // 这里的1.01默认为float64类型(64位系统下) + if buffer, err := gbinary.Encode(18, 300, 1.01); err != nil { glog.Error(err) } else { - var i1 int32 - var i2 int64 - if err := gbinary.Decode(buffer, &i1, &i2); err != nil { + var i1 int8 + var i2 int16 + var f3 float64 + if err := gbinary.Decode(buffer, &i1, &i2, &f3); err != nil { glog.Error(err) } else { - fmt.Println(i1, i2) + fmt.Println(i1, i2, f3) } } + // 编码/解析 int,自动识别变量长度 + fmt.Println(gbinary.DecodeToInt(gbinary.EncodeInt(1))) + fmt.Println(gbinary.DecodeToInt(gbinary.EncodeInt(300))) + fmt.Println(gbinary.DecodeToInt(gbinary.EncodeInt(70000))) + fmt.Println(gbinary.DecodeToInt(gbinary.EncodeInt(2000000000))) + fmt.Println(gbinary.DecodeToInt(gbinary.EncodeInt(500000000000))) + + // 编码/解析 uint,自动识别变量长度 + fmt.Println(gbinary.DecodeToUint(gbinary.EncodeUint(1))) + fmt.Println(gbinary.DecodeToUint(gbinary.EncodeUint(300))) + fmt.Println(gbinary.DecodeToUint(gbinary.EncodeUint(70000))) + fmt.Println(gbinary.DecodeToUint(gbinary.EncodeUint(2000000000))) + fmt.Println(gbinary.DecodeToUint(gbinary.EncodeUint(500000000000))) + // 编码/解析 int8/16/32/64 fmt.Println(gbinary.DecodeToInt8(gbinary.EncodeInt8(int8(100)))) fmt.Println(gbinary.DecodeToInt16(gbinary.EncodeInt16(int16(100)))) diff --git a/geg/encoding/gbinary/bits1.go b/geg/encoding/gbinary/bits1.go new file mode 100644 index 000000000..303ed2564 --- /dev/null +++ b/geg/encoding/gbinary/bits1.go @@ -0,0 +1,30 @@ +package main + +import ( + "fmt" + "gitee.com/johng/gf/g/encoding/gbinary" +) + +func main() { + // 传感器状态,0:已下线, 1:开启, 2:关闭, 3:待机 + count := 100 + status := 1 + + // 编码 + bits := make([]gbinary.Bit, 0) + for i := 0; i < count; i++ { + bits = gbinary.EncodeBits(bits, uint(status), 2) + } + buffer := gbinary.EncodeBitsToBytes(bits) + fmt.Println("buffer length:", len(buffer)) + + // 解码 + alivecount := 0 + sensorbits := gbinary.DecodeBytesToBits(buffer) + for i := 0; i < len(sensorbits); i += 2 { + if gbinary.DecodeBits(sensorbits[i:i+2]) == 1 { + alivecount++ + } + } + fmt.Println("alived sensor:", alivecount) +} diff --git a/geg/encoding/gbinary/bits2.go b/geg/encoding/gbinary/bits2.go new file mode 100644 index 000000000..07cf1abf9 --- /dev/null +++ b/geg/encoding/gbinary/bits2.go @@ -0,0 +1,30 @@ +package main + +import ( + "fmt" + "gitee.com/johng/gf/g/encoding/gbinary" +) + +func main() { + // Meta元数据文件数据结构:[键名哈希64(64bit,8byte) 键名长度(8bit,1byte) 键值长度(24bit,3byte) 数据文件偏移量(40bit,5byte)](变长) + hash := 521369841259754125 + klen := 12 + vlen := 35535 + offset := 80000000 + + // 编码 + bits := make([]gbinary.Bit, 0) + bits = gbinary.EncodeBits(bits, uint(hash), 64) + bits = gbinary.EncodeBits(bits, uint(klen), 8) + bits = gbinary.EncodeBits(bits, uint(vlen), 24) + bits = gbinary.EncodeBits(bits, uint(offset), 40) + buffer := gbinary.EncodeBitsToBytes(bits) + fmt.Println("meta length:", len(buffer)) + + // 解码 + metabits := gbinary.DecodeBytesToBits(buffer) + fmt.Println("hash :", gbinary.DecodeBits(metabits[0 : 64])) + fmt.Println("klen :", gbinary.DecodeBits(metabits[64 : 72])) + fmt.Println("vlen :", gbinary.DecodeBits(metabits[72 : 96])) + fmt.Println("offset:", gbinary.DecodeBits(metabits[96 : 136])) +}