and0rsk and0rsk - 6 months ago 59
Java Question

Convert an unsigned byte stream to signed bytestream Golang

What is the best way to convert an bytestream to a bytestream slice in Golang? Currently I'm trying to replicate a java program in golang and I believe I am having some issues with the fact that java reads the bytestream as a signed value, whereas golang treats it as an unsigned value.

When I print in Java note the negative values are different. Positive are the same:


Java:

8|-8|-58|-61|-56|-113|42|16|-64|2|24|-16|1

Golang:

8|248|198|195|200|143|42|16|192|2|2|240|1


Currently, my implementation right in GO looks like:

//open the file with os.open
//create new reader and unzip it

//reads from zip file and returns an array of bytes associated with it.
data, err := ioutil.ReadAll(fz)
if err != nil {
return nil, err
}
//reflect.TypeOf shows this is a []uint8
//I want this to be a []int8 (so signed).


In Java the implementation was pretty much:

//create buffer reader
//create input stream
//create datainput stream
//use the .Read function to get the values required.


I didn't see any easy way to typecast it quickly to a signed int (maybe I'm wrong). I could try to iterate through the entire slice, converting each value to a signed int, but that approach seems rather messy. It would also require me to operate on each. Is there a cleaner way of converting the slice?

Answer

You can use unsafe.Pointer if you know exactly what you are doing. Because as its name suggests, it is unsafe. Therefore, it will blow up if you use it unwisely.

package main

import (
    "fmt"
    "unsafe"
)

func main() {
    unsigned := make([]uint8, 0)
    unsigned = append(unsigned, 128)
    unsigned = append(unsigned, 255)

    signed := *(*[]int8)(unsafe.Pointer(&unsigned))
    fmt.Printf("%d : %d\n", signed[0], unsigned[0])
    fmt.Printf("%d : %d\n", signed[1], unsigned[1])
}
// -128 : 128
// -1 : 255

You can find this example on the Go playground