从字节切片解码数据为Uint32

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

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)
}

英文:
  1. package main
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. "fmt"
  6. )
  7. func main() {
  8. aa := uint(0xFFFFFFFF)
  9. fmt.Println(aa)
  10. byteNewbuf := []byte{0xFF, 0xFF, 0xFF, 0xFF}
  11. buf := bytes.NewBuffer(byteNewbuf)
  12. tt, _ := binary.ReadUvarint(buf)
  13. fmt.Println(tt)
  14. }

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对象之一来完成这个操作。例如:

  1. package main
  2. import (
  3. "encoding/binary"
  4. "fmt"
  5. )
  6. func main() {
  7. aa := uint(0x7FFFFFFF)
  8. fmt.Println(aa)
  9. slice := []byte{0xFF, 0xFF, 0xFF, 0x7F}
  10. tt := binary.LittleEndian.Uint32(slice)
  11. fmt.Println(tt)
  12. }

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

英文:

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

  1. package main
  2. import (
  3. "encoding/binary"
  4. "fmt"
  5. )
  6. func main() {
  7. aa := uint(0x7FFFFFFF)
  8. fmt.Println(aa)
  9. slice := []byte{0xFF, 0xFF, 0xFF, 0x7F}
  10. tt := binary.LittleEndian.Uint32(slice)
  11. fmt.Println(tt)
  12. }

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时确实存在问题。

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

for BE or

  1. tt := uint32(buf[0]) | uint32(buf[1])&lt;&lt;8 | uint32(buf[2]) &lt;&lt;16 |
  2. 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版本

  1. package main
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. "fmt"
  6. "log"
  7. )
  8. func main() {
  9. aa := uint(0xFFFFFF0F)
  10. fmt.Println(aa)
  11. tt := uint32(0)
  12. byteNewbuf := []byte{0x0F, 0xFF, 0xFF, 0xFF}
  13. buf := bytes.NewBuffer(byteNewbuf)
  14. err := binary.Read(buf, binary.LittleEndian, &tt)
  15. if err != nil {
  16. log.Fatalf("Decode failed: %s", err)
  17. }
  18. fmt.Println(tt)
  19. }

结果是

  1. 4294967055
  2. 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

  1. package main
  2. import (
  3. &quot;bytes&quot;
  4. &quot;encoding/binary&quot;
  5. &quot;fmt&quot;
  6. &quot;log&quot;
  7. )
  8. func main() {
  9. aa := uint(0xFFFFFF0F)
  10. fmt.Println(aa)
  11. tt := uint32(0)
  12. byteNewbuf := []byte{0x0F, 0xFF, 0xFF, 0xFF}
  13. buf := bytes.NewBuffer(byteNewbuf)
  14. err := binary.Read(buf, binary.LittleEndian, &amp;tt)
  15. if err != nil {
  16. log.Fatalf(&quot;Decode failed: %s&quot;, err)
  17. }
  18. fmt.Println(tt)
  19. }

Result is

  1. 4294967055
  2. 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 函数。

例如,

  1. package main
  2. import (
  3. &quot;bytes&quot;
  4. &quot;encoding/binary&quot;
  5. &quot;fmt&quot;
  6. )
  7. func main() {
  8. buf := make([]byte, 10)
  9. x := uint64(0xFFFFFFFF)
  10. fmt.Printf(&quot;%2d %2d %v\n&quot;, x, len(buf), buf)
  11. n := binary.PutUvarint(buf, x)
  12. buf = buf[:n]
  13. fmt.Printf(&quot;%2d %2d %v\n&quot;, x, len(buf), buf)
  14. y, err := binary.ReadUvarint(bytes.NewBuffer(buf))
  15. if err != nil {
  16. fmt.Println(err)
  17. return
  18. }
  19. fmt.Printf(&quot;%2d %2d %v\n&quot;, y, len(buf), buf)
  20. }

输出:

  1. 4294967295 10 [0 0 0 0 0 0 0 0 0 0]
  2. 4294967295 5 [255 255 255 255 15]
  3. 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,

  1. package main
  2. import (
  3. &quot;bytes&quot;
  4. &quot;encoding/binary&quot;
  5. &quot;fmt&quot;
  6. )
  7. func main() {
  8. buf := make([]byte, 10)
  9. x := uint64(0xFFFFFFFF)
  10. fmt.Printf(&quot;%2d %2d %v\n&quot;, x, len(buf), buf)
  11. n := binary.PutUvarint(buf, x)
  12. buf = buf[:n]
  13. fmt.Printf(&quot;%2d %2d %v\n&quot;, x, len(buf), buf)
  14. y, err := binary.ReadUvarint(bytes.NewBuffer(buf))
  15. if err != nil {
  16. fmt.Println(err)
  17. return
  18. }
  19. fmt.Printf(&quot;%2d %2d %v\n&quot;, y, len(buf), buf)
  20. }

Output:

  1. 4294967295 10 [0 0 0 0 0 0 0 0 0 0]
  2. 4294967295 5 [255 255 255 255 15]
  3. 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:

确定