Files
zogo/bytepacket/bytepacket.go
T
4566704 f9f7c7c92f feat(bytepacket): 自 go-hua 迁入二进制封包工具
- 小端序读写, 兼容易语言协议(GBK 字符串/易语言日期)
- 附测试、examples/bytepacket 例程与包 README
2026-09-20 12:25:35 +08:00

282 lines
6.1 KiB
Go

// Package bytepacket 提供二进制封包/解包(小端序,兼容易语言协议,含 GBK 字符串与易语言日期转换)。
package bytepacket
import (
"bytes"
"encoding/binary"
"fmt"
"io"
"math"
"time"
"golang.org/x/text/encoding/simplifiedchinese"
"golang.org/x/text/transform"
)
// Packet 二进制封包读写器(小端序),写入后经 GetData 取出完整报文
type Packet struct {
buffer *bytes.Buffer
}
// NewPacket 新建封包
func NewPacket(b []byte) *Packet {
return &Packet{buffer: bytes.NewBuffer(b)}
}
// SetData 设置数据
func (p *Packet) SetData(b []byte) {
p.buffer = bytes.NewBuffer(b)
}
// GetData 获取数据
func (p *Packet) GetData() []byte {
return p.buffer.Bytes()
}
// ReadInt8 读取int8
func (p *Packet) ReadInt8() int8 {
var val int8 = 0
binary.Read(p.buffer, binary.LittleEndian, &val)
return val
}
// WriteInt8 写入int8
func (p *Packet) WriteInt8(val int8) {
binary.Write(p.buffer, binary.LittleEndian, &val)
}
// ReadUInt8 读取uint8
func (p *Packet) ReadUInt8() uint8 {
var val uint8 = 0
binary.Read(p.buffer, binary.LittleEndian, &val)
return val
}
// WriteUInt8 写入uint8
func (p *Packet) WriteUInt8(val uint8) {
binary.Write(p.buffer, binary.LittleEndian, &val)
}
// ReadInt16 读取int16
func (p *Packet) ReadInt16() int16 {
var val int16 = 0
binary.Read(p.buffer, binary.LittleEndian, &val)
return val
}
// WriteInt16 写入int16
func (p *Packet) WriteInt16(val int16) {
binary.Write(p.buffer, binary.LittleEndian, &val)
}
// ReadUInt16 读取uint16
func (p *Packet) ReadUInt16() uint16 {
var val uint16 = 0
binary.Read(p.buffer, binary.LittleEndian, &val)
return val
}
// WriteUInt16 写入uint16
func (p *Packet) WriteUInt16(val uint16) {
binary.Write(p.buffer, binary.LittleEndian, &val)
}
// ReadInt32 读取int32
func (p *Packet) ReadInt32() int32 {
var val int32 = 0
binary.Read(p.buffer, binary.LittleEndian, &val)
return val
}
// WriteUInt32 写入uint32
func (p *Packet) WriteUInt32(val uint32) {
binary.Write(p.buffer, binary.LittleEndian, &val)
}
// ReadUInt32 读取uint32
func (p *Packet) ReadUInt32() uint32 {
var val uint32 = 0
binary.Read(p.buffer, binary.LittleEndian, &val)
return val
}
// WriteInt32 写入int32
func (p *Packet) WriteInt32(val int32) {
binary.Write(p.buffer, binary.LittleEndian, &val)
}
// ReadInt64 读取int64
func (p *Packet) ReadInt64() int64 {
var val int64 = 0
binary.Read(p.buffer, binary.LittleEndian, &val)
return val
}
// WriteInt64 写入int64
func (p *Packet) WriteInt64(val int64) {
binary.Write(p.buffer, binary.LittleEndian, &val)
}
// ReadUInt64 读取uint64
func (p *Packet) ReadUInt64() uint64 {
var val uint64 = 0
binary.Read(p.buffer, binary.LittleEndian, &val)
return val
}
// WriteUInt64 写入uint64
func (p *Packet) WriteUInt64(val uint64) {
binary.Write(p.buffer, binary.LittleEndian, &val)
}
// ReadFloat32 读取float32
func (p *Packet) ReadFloat32() float32 {
var val float32 = 0
binary.Read(p.buffer, binary.LittleEndian, &val)
return val
}
// WriteFloat32 写入float32
func (p *Packet) WriteFloat32(val float32) {
binary.Write(p.buffer, binary.LittleEndian, &val)
}
// ReadFloat64 读取float64
func (p *Packet) ReadFloat64() float64 {
var val float64 = 0
binary.Read(p.buffer, binary.LittleEndian, &val)
return val
}
// WriteFloat64 写入float64
func (p *Packet) WriteFloat64(val float64) {
binary.Write(p.buffer, binary.LittleEndian, &val)
}
// ReadStringGbk 读取GBK字符串
func (p *Packet) ReadStringGbk() (string, error) {
var len int16 = 0
binary.Read(p.buffer, binary.LittleEndian, &len)
buf := p.buffer.Next(int(len))
if len == 0 {
return "", nil
}
if len < 0 {
return "", fmt.Errorf("invalid string length: %d", len)
}
bytes, err := GbkToUtf8(buf)
if err != nil {
return "", err
}
return string(bytes), nil
}
// WriteStringGbk 写入GBK字符串
func (p *Packet) WriteStringGbk(str string) error {
bytes, err := Utf8ToGbk([]byte(str))
if err != nil {
return err
}
var len int16 = int16(len(bytes))
err = binary.Write(p.buffer, binary.LittleEndian, &len)
if err != nil {
return err
}
_, err = p.buffer.Write(bytes)
if err != nil {
return err
}
return err
}
// ReadString 读取字符串
func (p *Packet) ReadString() (string, error) {
var len int16 = 0
err := binary.Read(p.buffer, binary.LittleEndian, &len)
if err != nil {
return "", err
}
if len == 0 {
return "", nil
}
if len < 0 {
return "", fmt.Errorf("invalid string length: %d", len)
}
buf := p.buffer.Next(int(len))
return string(buf), nil
}
// WriteString 写入字符串
func (p *Packet) WriteString(str string) error {
bytes := []byte(str)
var len int16 = int16(len(bytes))
err := binary.Write(p.buffer, binary.LittleEndian, &len)
if err != nil {
return err
}
_, err = p.buffer.Write(bytes)
if err != nil {
return err
}
return nil
}
// ReadBytes 读取字节集
func (p *Packet) ReadBytes() []byte {
var len int32 = 0
binary.Read(p.buffer, binary.LittleEndian, &len)
if len == 0 {
return nil
}
if len < 0 {
return nil
}
buf := p.buffer.Next(int(len))
return buf
}
// WriteBytes 写入字节集
func (p *Packet) WriteBytes(data []byte) error {
var len int32 = int32(len(data))
err := binary.Write(p.buffer, binary.LittleEndian, &len)
if err != nil {
return err
}
_, err = p.buffer.Write(data)
if err != nil {
return err
}
return err
}
// ReadElangDateTime 读取易语言日期时间
func (p *Packet) ReadElangDateTime() time.Time {
var f float64
binary.Read(p.buffer, binary.LittleEndian, &f)
t := time.Date(1899, 12, 30, 0, 0, 0, 0, time.Local)
msStr := fmt.Sprint("+", uint64(math.Floor(f*86400*1000+0.5)), "ms")
ms, _ := time.ParseDuration(msStr)
return t.Add(ms)
}
// GbkToUtf8 GBK 转 UTF-8
func GbkToUtf8(s []byte) ([]byte, error) {
reader := transform.NewReader(bytes.NewReader(s), simplifiedchinese.GBK.NewDecoder())
d, e := io.ReadAll(reader)
if e != nil {
return nil, e
}
return d, nil
}
// Utf8ToGbk UTF-8 转 GBK
func Utf8ToGbk(s []byte) ([]byte, error) {
reader := transform.NewReader(bytes.NewReader(s), simplifiedchinese.GBK.NewEncoder())
d, e := io.ReadAll(reader)
if e != nil {
return nil, e
}
return d, nil
}