string - बाइट सरणी को स्ट्रिंग में कनवर्ट करने का सबसे अच्छा तरीका क्या है?




go byte (8)

string डेटा का एक गुच्छा स्थानांतरित करने के लिए मुझे [100]byte पढ़ने की जरूरत है।

चूंकि सभी string ठीक से 100 लंबे नहीं हैं, byte array का शेष भाग 0 एस के साथ गद्देदार है।

यदि मैं string(byteArray[:]) द्वारा string करने के लिए [100]byte को तब्दील करता हूं, तो पूंछ 0 को ^@^@ एस के रूप में प्रदर्शित किया जाता है।

सी में string 0 पर समाप्त हो जाएगी, इसलिए मुझे आश्चर्य है कि string byte array को स्मार्ट रूप से स्थानांतरित करने का सबसे अच्छा तरीका क्या है।


उदाहरण के लिए,

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

जब आप सरणी में गैर-शून्य बाइट्स की सटीक लंबाई नहीं जानते हैं, तो आप इसे पहले ट्रिम कर सकते हैं:

स्ट्रिंग (बाइट्स। टीआरएम (एआर, "\ x00"))


निम्नलिखित कोड '\ 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))
}

शून्य-बाइट की तलाश में बाइट सरणी को आसानी से स्कैन करने के लिए यह तेज़ी से हो सकता है, खासकर यदि आपके अधिकांश तार कम हैं।


बाइट स्लाइस में डेटा पढ़ने वाले विधियों को पढ़ने वाले बाइट्स की संख्या लौटाती है। आपको उस नंबर को सहेजना चाहिए और फिर अपनी स्ट्रिंग बनाने के लिए इसका उपयोग करना चाहिए। n बाइट्स पढ़ने की संख्या होने के नाते, आपका कोड इस तरह दिखेगा:

s := string(byteArray[:n])

अगर किसी कारण से आपके पास n नहीं है, तो आप इसे खोजने के लिए बाइट्स पैकेज का उपयोग कर सकते हैं, मानते हैं कि आपके इनपुट में इसका कोई शून्य चरित्र नहीं है।

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

या जैसा कि आईसीज़ा ने बताया, आप नीचे दिए गए कोड का उपयोग कर सकते हैं:

n := bytes.IndexByte(byteArray, 0)

यह क्यों नहीं?

bytes.NewBuffer(byteArray).String()

व्हाट अबाउट?

s := string(byteArray[:])

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

  • पढ़ने के लिए सरणी के बजाय स्लाइस का प्रयोग करें। उदाहरण के लिए 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





byte