从字节切片解码数据为Uint32

huangapple go评论73阅读模式
英文:

Decoding data from a byte slice to Uint32

问题

package main

import (
"bytes"
"encoding/binary"
"fmt"
)

func main() {
aa := uint(0xFFFFFFFF)
fmt.Println(aa)
byteNewbuf := []byte{0xFF, 0xFF, 0xFF, 0xFF}
buf := bytes.NewBuffer(byteNewbuf)
tt, _ := binary.ReadUvarint(buf)
fmt.Println(tt)
}

英文:
package main

import (
        "bytes"
        "encoding/binary"
        "fmt"
)

func main() {
        aa := uint(0xFFFFFFFF)
        fmt.Println(aa)
        byteNewbuf := []byte{0xFF, 0xFF, 0xFF, 0xFF}
        buf := bytes.NewBuffer(byteNewbuf)
        tt, _ := binary.ReadUvarint(buf)
        fmt.Println(tt)
}

Need to convert 4 bytes array to uint32 but why the results are not same ?
go verion : beta 1.1

答案1

得分: 13

你可以使用encoding/binary包中的ByteOrder对象之一来完成这个操作。例如:

package main

import (
        "encoding/binary"
        "fmt"
)

func main() {
        aa := uint(0x7FFFFFFF)
        fmt.Println(aa)
        slice := []byte{0xFF, 0xFF, 0xFF, 0x7F}
        tt := binary.LittleEndian.Uint32(slice)
        fmt.Println(tt)
}

如果你的数据是大端格式的,你可以使用相同的方法在binary.BigEndian上进行操作。

英文:

You can do this with one of the ByteOrder objects from the encoding/binary package. For instance:

package main

import (
        "encoding/binary"
        "fmt"
)

func main() {
        aa := uint(0x7FFFFFFF)
        fmt.Println(aa)
        slice := []byte{0xFF, 0xFF, 0xFF, 0x7F}
	    tt := binary.LittleEndian.Uint32(slice)
        fmt.Println(tt)
}

If your data is in big endian format, you can instead use the same methods on binary.BigEndian.

答案2

得分: 5

tt := uint32(buf[0])<<24 | uint32(buf1)<<16 | uint32(buf2) <<8 |
uint32(buf3)

for BE or

tt := uint32(buf[0]) | uint32(buf1)<<8 | uint32(buf2) <<16 |
uint32(buf3) <<24

for LE.

varint是一种不同类型的编码(32位数字在编码形式中可以有多达5个字节,64位数字最多可以有10个字节)。

  • 不需要为[]byte创建缓冲区。直接在字节切片上使用Varint或Uvarint。

  • 您正在丢弃函数返回的错误。第二个结果指示读取了多少字节或是否存在问题。将0xff、0xff、0xff、0xff解码为uvarint时确实存在问题。

英文:
tt := uint32(buf[0])&lt;&lt;24 | uint32(buf[1])&lt;&lt;16 | uint32(buf[2]) &lt;&lt;8 |
        uint32(buf[3])

for BE or

tt := uint32(buf[0]) | uint32(buf[1])&lt;&lt;8 | uint32(buf[2]) &lt;&lt;16 |
        uint32(buf[3]) &lt;&lt;24

for LE.

[u]varint is a different kind of encoding (32 bit numbers can have as much as 5 bytes in the encoded form, 64 bit numbers up to 10).

  • No need to create a buffer for []byte. Use Varint or Uvarint directly on the byte slice instead.

  • You're throwing away the error returned by the function. The second result indicates how many bytes were read or if there was a problem. There is a problem while decoding 0xff, 0xff, 0xff, 0xff as an uvarint.

答案3

得分: 4

这里是如何使用encoding/binary包来实现你想要的功能。请注意,你不应该使用任何var函数,因为它们会进行可变长度编码。

Playground版本

package main

import (
    "bytes"
    "encoding/binary"
    "fmt"
    "log"
)

func main() {
    aa := uint(0xFFFFFF0F)
    fmt.Println(aa)
    tt := uint32(0)

    byteNewbuf := []byte{0x0F, 0xFF, 0xFF, 0xFF}
    buf := bytes.NewBuffer(byteNewbuf)
    err := binary.Read(buf, binary.LittleEndian, &tt)
    if err != nil {
        log.Fatalf("Decode failed: %s", err)
    }
    fmt.Println(tt)
}

结果是

4294967055
4294967055
英文:

Here is how to use the encoding/binary package to do what you want. Note that you don't want to use any of the var functions as those do variable length encoding.

Playground version

package main

import (
	&quot;bytes&quot;
	&quot;encoding/binary&quot;
	&quot;fmt&quot;
	&quot;log&quot;
)

func main() {
	aa := uint(0xFFFFFF0F)
	fmt.Println(aa)
	tt := uint32(0)

	byteNewbuf := []byte{0x0F, 0xFF, 0xFF, 0xFF}
	buf := bytes.NewBuffer(byteNewbuf)
	err := binary.Read(buf, binary.LittleEndian, &amp;tt)
	if err != nil {
		log.Fatalf(&quot;Decode failed: %s&quot;, err)
	}
	fmt.Println(tt)
}

Result is

4294967055
4294967055

答案4

得分: -1

> 数字类型
>
> byte 是 uint8 的别名

由于 byteuint8 的别名,你的问题,“需要将 4 字节数组转换为 uint32”,已经有了答案:

如何在 Go 中将 [4]uint8 转换为 uint32?

> 二进制包
>
> [Uvarints 和] Varints 是一种使用一个或多个字节对整数进行编码的方法;绝对值较小的数字占用较少的字节。有关规范,请参见
> http://code.google.com/apis/protocolbuffers/docs/encoding.html

由于 Uvarint 是一种特殊的整数表示和存储形式,你应该只在使用 Uvarint 函数写入的值上使用 ReadUvarint 函数。

例如,

package main

import (
	&quot;bytes&quot;
	&quot;encoding/binary&quot;
	&quot;fmt&quot;
)

func main() {
	buf := make([]byte, 10)
	x := uint64(0xFFFFFFFF)
	fmt.Printf(&quot;%2d %2d %v\n&quot;, x, len(buf), buf)
	n := binary.PutUvarint(buf, x)
	buf = buf[:n]
	fmt.Printf(&quot;%2d %2d %v\n&quot;, x, len(buf), buf)
	y, err := binary.ReadUvarint(bytes.NewBuffer(buf))
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Printf(&quot;%2d %2d %v\n&quot;, y, len(buf), buf)
}

输出:

4294967295 10 [0 0 0 0 0 0 0 0 0 0]
4294967295  5 [255 255 255 255 15]
4294967295  5 [255 255 255 255 15]
英文:

> Numeric types
>
> byte alias for uint8

Since byte is an alias for uint8, your question, "Need to convert 4 bytes array to uint32", has already been answered:

How to convert [4]uint8 into uint32 in Go?

> Package binary
>
> [Uvarints and] Varints are a method of encoding integers using one
> or more bytes; numbers with smaller absolute value take a smaller
> number of bytes. For a specification, see
> http://code.google.com/apis/protocolbuffers/docs/encoding.html.

Since Uvarints are a peculiar form of integer representation and storage, you should only use the ReadUvarint function on values that have been written with the Uvarint function.

For example,

package main

import (
	&quot;bytes&quot;
	&quot;encoding/binary&quot;
	&quot;fmt&quot;
)

func main() {
	buf := make([]byte, 10)
	x := uint64(0xFFFFFFFF)
	fmt.Printf(&quot;%2d %2d %v\n&quot;, x, len(buf), buf)
	n := binary.PutUvarint(buf, x)
	buf = buf[:n]
	fmt.Printf(&quot;%2d %2d %v\n&quot;, x, len(buf), buf)
	y, err := binary.ReadUvarint(bytes.NewBuffer(buf))
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Printf(&quot;%2d %2d %v\n&quot;, y, len(buf), buf)
}

Output:

4294967295 10 [0 0 0 0 0 0 0 0 0 0]
4294967295  5 [255 255 255 255 15]
4294967295  5 [255 255 255 255 15]

huangapple
  • 本文由 发表于 2013年4月6日 16:49:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/15848830.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定