development

0으로 끝나는 바이트 배열을 문자열로 변환하는 방법은 무엇입니까?

big-blog 2020. 2. 14. 23:44
반응형

0으로 끝나는 바이트 배열을 문자열로 변환하는 방법은 무엇입니까?


[100]byte많은 string데이터 를 전송 하기 위해 읽어야 합니다 .

모든 strings의 길이가 정확히 100자인 것은 아니므로 나머지 부분은 s byte array로 채워집니다 0.

내가 tansfer 경우 [100]bytestring기준 : string(byteArray[:])의 미행 0들로 표시됩니다 ^@^@의.

C에서는 string의지 가 끝나기 때문에 Golang에서 0a byte array현명하게 전환하는 가장 좋은 방법이 무엇인지 궁금합니다 string.


바이트 슬라이스로 데이터를 읽는 메소드는 읽은 바이트 수를 리턴합니다. 해당 번호를 저장 한 다음이를 사용하여 문자열을 작성해야합니다. n읽은 바이트 수이므로 코드는 다음과 같습니다.

s := string(byteArray[:n])

어떤 이유로 든이없는 경우 n입력에 null 문자가 없다고 가정하면 bytes 패키지를 사용하여 찾을 수 있습니다.

n := bytes.Index(byteArray, []byte{0})

또는 icza가 지적했듯이 아래 코드를 사용할 수 있습니다.

n := bytes.IndexByte(byteArray, 0)

는 어때?

s := string(byteArray[:])

간단한 솔루션 :

str := fmt.Sprintf("%s", byteArray)

나는 이것이 얼마나 성능이 있는지 잘 모르겠습니다.


예를 들어

package main

import "fmt"

func CToGoString(c []byte) string {
    n := -1
    for i, b := range c {
        if b == 0 {
            break
        }
        n = i
    }
    return string(c[:n+1])
}

func main() {
    c := [100]byte{'a', 'b', 'c'}
    fmt.Println("C: ", len(c), c[:4])
    g := CToGoString(c[:])
    fmt.Println("Go:", len(g), g)
}

산출:

C:  100 [97 98 99 0]
Go: 3 abc

다음 코드는 '\ 0'을 찾고 있으며 질문의 가정에 따라 '\ 0'이 아닌 모든 '\ 0'이 앞에 오므로 배열을 정렬 된 것으로 간주 할 수 있습니다. 배열이 데이터 내에 '\ 0'을 포함 할 수 있으면이 가정은 유지되지 않습니다.

이진 검색을 사용하여 첫 번째 0 바이트의 위치를 ​​찾은 다음 슬라이스하십시오.

다음과 같이 0 바이트를 찾을 수 있습니다.

package main

import "fmt"

func FirstZero(b []byte) int {
    min, max := 0, len(b)
    for {
        if min + 1 == max { return max }
        mid := (min + max) / 2
        if b[mid] == '\000' {
            max = mid
        } else {
            min = mid
        }
    }
    return len(b)
}
func main() {
    b := []byte{1, 2, 3, 0, 0, 0}
    fmt.Println(FirstZero(b))
}

특히 대부분의 문자열이 짧은 경우 바이트 배열을 순전히 스캔하여 0 바이트를 찾는 것이 더 빠를 수 있습니다.


배열에서 0이 아닌 바이트가 아닌 정확한 길이를 모르면 먼저 트리밍 할 수 있습니다.

문자열 (bytes.Trim (arr, "\ x00"))


성능 조정에만 사용하십시오.

package main

import (
    "fmt"
    "reflect"
    "unsafe"
)

func BytesToString(b []byte) string {
    bh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
    sh := reflect.StringHeader{bh.Data, bh.Len}
    return *(*string)(unsafe.Pointer(&sh))
}

func StringToBytes(s string) []byte {
    sh := (*reflect.StringHeader)(unsafe.Pointer(&s))
    bh := reflect.SliceHeader{sh.Data, sh.Len, 0}
    return *(*[]byte)(unsafe.Pointer(&bh))
}

func main() {
    b := []byte{'b', 'y', 't', 'e'}
    s := BytesToString(b)
    fmt.Println(s)
    b = StringToBytes(s)
    fmt.Println(string(b))
}

왜 안돼?

bytes.NewBuffer(byteArray).String()

  • 읽기 대신 배열 대신 슬라이스를 사용하십시오. 예를 들어 io.Reader배열이 아닌 슬라이스를 허용합니다.

  • 제로 패딩 대신 슬라이싱을 사용하십시오.

예:

buf := make([]byte, 100)
n, err := myReader.Read(buf)
if n == 0 && err != nil {
        log.Fatal(err)
}

consume(buf[:n]) // consume will see exact (not padded) slice of read data

공황 상태에 빠졌을 때 몇 가지 방법을 시도했습니다.

런타임 오류 : 슬라이스 범위를 벗어났습니다.

그러나 이것은 마침내 효과가있었습니다.

string(Data[:])


더 빠른 방법은 다음과 같습니다.

resp, _ := http.Get("https://www.something.com/something.xml")
bytes, _ := ioutil.ReadAll(resp.Body)
resp.Body.Close()
fmt.Println(string(bytes)) //just convert with string() function

재귀 적 솔루션을 사용하는 경우

func CToGoString(c []byte, acc string) string {

    if len(c) == 0 {
        return acc
    } else {
        head := c[0]
        tail := c[1:]
        return CToGoString(tail, acc + fmt.Sprintf("%c", head))
    }
}

func main() {
    b := []byte{some char bytes}
    fmt.Println(CToGoString(b, ""))
}

참고 URL : https://stackoverflow.com/questions/14230145/how-to-convert-a-zero-terminated-byte-array-to-string



반응형