2022-09-19 encoding/binary与bytes包配合使用

binary与bytes包配合使用

1.bytes.Reader

bytes.Reader是一个实现了io.Reader接口的结构体,用于方便从指定的切片中读取数据。

可以从一个已有的切片构造bytes.Reader,方便读写切片。

构造:

func NewReader(b []byte) *Reader

操作:

func (r *Reader) Read(b []byte) (n int, err error)

Reader从底层切片中到目标切片b中,读取数量为b的大小,如果不够读取源切片全部数据,返回读取到的字节数量。

2.bytes.Buffer

该接口是实现了io.Reader和io.Writer接口的字节缓。

构造:

//方法1:根据指定的切片构造Buffer
func NewBuffer(buf []byte) *Buffer
//方法2:直接构造空Buffer
buf := new(bytes.Buffer)

使用:

//从buffer中读取len(p)大小的数据
func (b *Buffer) Read(p []byte) (n int, err error)
//往buffer中写入p切片中的数据
func (b *Buffer) Write(p []byte) (n int, err error)

3.binary.Read

从r中读取binary编码的数据并赋给data,data必须是一个指向定长值的指针或者定长值的切片。

原型:

func Read(r io.Reader, order ByteOrder, data interface{}) error

参数1:实现io.Reader接口的结构

参数2:大小端字节序

参数3:要从r中读取到的二进制数据保存到data变量中

如果有错误返回error

使用:

bytes.Reader结构实现了io.Reader接口,所以可以使用binary.Read从bytes.Reader中读取二进制切片数据到指定data变量中。

var pi float64
b := []byte{0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x09, 0x40}
Reader := bytes.NewReader(b)
err := binary.Read(Reader, binary.LittleEndian, &pi)
if err != nil {
    fmt.Println("binary.Read failed:", err)
}
fmt.Print(pi)

4.binary.Write

把data数据按照指定的字节序写到w中,w是实现了io.Writer接口的类型。

原型:

func Write(w io.Writer, order ByteOrder, data interface{}) error

参数1:w是实现了io.Writer接口类型的数据。

参数2:大小端字节序

参数3: 把data变量中的二进制数据写到w中。

使用:

bytes.Buffer结构实现了io.Reader,io.Writer接口,所以可以使用binary.Write()将data变量的数据,写入到buffer中。

buf := new(bytes.Buffer)
var pi float64 = math.Pi
err := binary.Write(buf, binary.LittleEndian, pi)
//将pi写入到buffer中
if err != nil {
    fmt.Println("binary.Write failed:", err)
}
fmt.Printf("% x", buf.Bytes())

example

//server
package main
import (
    "bytes"
    "encoding/binary"
    "fmt"
    "log"
    "net"
    "unsafe"
)
func init() {
    log.SetFlags(log.Lshortfile)
}
type MessageHeader struct {
    MessageType   int32
    MessageLength int32
}
func Handle(conn net.Conn) {
    //处理连接的读写
    message_header := MessageHeader{}
//go语言的sizeof参数是实例出的对象的大小,不能传类型,跟C++不同
    bin_data := make([]byte, unsafe.Sizeof(message_header))
    _, err := conn.Read(bin_data)
    if err != nil {
        log.Println("conn.Read,error", err)
        return
    }
    //创建一个基于bin_data的Bytes.Reader
    reader := bytes.NewReader(bin_data)
    //把读到的数据写入header中
    err = binary.Read(reader, binary.LittleEndian, &message_header)
    if err != nil {
        log.Println("binary.Read error = ", err)
        return
    }
    fmt.Println(message_header)
    conn.Write(bin_data)
}
func main() {
    listenner, err := net.Listen("tcp", "127.0.0.1:9000")
    if err != nil {
        log.Fatalln("net.Listen error:=", err)
    }
    for {
        conn, err := listenner.Accept()
        if err != nil {
            log.Println("listenner.Accept() error:=", err)
            continue
        }
        go Handle(conn)
    }
}
//client
package main
import (
    "bytes"
    "encoding/binary"
    "fmt"
    "log"
    "net"
    "time"
    "unsafe"
)
type MessageHeader struct {
    MessageType   int32 //这里有个坑,请不要定义int类型,否则binary解析会有问题,因为int大小根据平台而定,不是定长的
    MessageLength int32
}
func init() {
    log.SetFlags(log.Lshortfile)
}
func main() {
    conn, err := net.Dial("tcp", "127.0.0.1:9000")
    if err != nil {
        log.Panicln("net.Dial errr,", err)
    }
    buffer := new(bytes.Buffer)
    header := &MessageHeader{
        MessageType:   1,
        MessageLength: 20,
    }
    err = binary.Write(buffer, binary.LittleEndian, header)
    if err != nil {
        log.Println("binary.Write err,", err)
        return
    }
    _, err = conn.Write(buffer.Bytes())
    if err != nil {
        log.Println("conn.Wirte err,", err)
        return
    }
    bin_data := make([]byte, unsafe.Sizeof(header))
    conn.Read(bin_data)
    target := &MessageHeader{}
    reader := bytes.NewReader(bin_data)
    binary.Read(reader, binary.LittleEndian, target)
    fmt.Println(target)
    time.Sleep(time.Second * 5)
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容