কিভাবে একটি শূন্য-সমাপ্ত বাইট অ্যারে স্ট্রিংয়ে রূপান্তর করবেন?


502

[100]byteএকগুচ্ছ stringডেটা স্থানান্তর করতে আমার পড়তে হবে ।

যেহেতু সমস্ত stringগুলি সূক্ষ্মভাবে 100 টি অক্ষর দীর্ঘ নয়, এর অবশিষ্ট অংশটি এস byte arrayদিয়ে প্যাড করে 0

যদি আমি রূপান্তর [100]byteকরার stringদ্বারা: string(byteArray[:]), পিছাড়ী 0s হিসেবে প্রদর্শিত হয় ^@^@সে।

সি ইন stringউপর বন্ধ করে দেব 0, তাই আমি ভাবছি সবচেয়ে ভালো উপায় রূপান্তর করার জন্য কি byte arrayকরতে stringGolang হবে।


3
@ আন্ড্রেলাস্লো: খেলার মাঠে খেলাগুলি প্রদর্শিত ^@হয় না তবে আপনি যদি এটি টার্মিনালে বা এর অনুরূপ কিছু পরীক্ষা করে দেখেন তবে তা সেখানে হত। এর কারণটি হ'ল গো, বাইট অ্যারেগুলিকে স্ট্রিংতে রূপান্তর করা বন্ধ করে না যখন এটি একটি 0. খুঁজে পেয়েছে len(string(bytes))আপনার উদাহরণে 5 টি নয় এবং 1 এটি স্ট্রিং পুরোপুরি (জিরো সহ) মুদ্রিত কিনা আউটপুট ফাংশনের উপর নির্ভর করে অথবা না.
নিমো

8
Http প্রতিক্রিয়া বডি জন্য, ব্যবহার করুন string(body)
ইভান চউ

উত্তর:


513

বাইট স্লাইসে ডেটা পড়ার পদ্ধতিগুলি পঠিত বাইটের সংখ্যা ফেরত দেয়। আপনার সেই নম্বরটি সংরক্ষণ করা উচিত এবং তারপরে আপনার স্ট্রিং তৈরি করতে এটি ব্যবহার করা উচিত যদি nপঠিত বাইটের সংখ্যা হয় তবে আপনার কোডটি দেখতে এই জাতীয় দেখাচ্ছে:

s := string(byteArray[:n])

পূর্ণ স্ট্রিং রূপান্তর করতে এটি ব্যবহার করা যেতে পারে:

s := string(byteArray[:len(byteArray)])

এটি সমান:

s := string(byteArray)

যদি কোনও কারণে আপনি না জানেন তবে nআপনি bytesপ্যাকেজটি এটির জন্য ব্যবহার করতে পারেন , ধরে নেওয়া আপনার ইনপুটটিতে কোনও নাল অক্ষর এমবেড করা নেই।

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

অথবা আইকজা নির্দেশিত হিসাবে আপনি নীচের কোডটি ব্যবহার করতে পারেন:

n := bytes.IndexByte(byteArray, 0)

2
আমি জানি যে আমি এক বছর দেরিতে আছি, তবে আমার উল্লেখ করা উচিত যে বেশিরভাগ পদ্ধতিগুলি বাইটের সংখ্যাটি পড়ে থাকে। উদাহরণস্বরূপ, বাইনারি। পড়ুন () একটি [32] বাইটে পড়তে পারে তবে আপনি 32 টি বাইট পূরণ করেছেন কিনা তা জানেন না।
এরিক লেগারগ্রেন

7
আপনার 1 টি বাইটযুক্ত বাইট স্লাইসের পরিবর্তে bytes.IndexByte()কোনটি অনুসন্ধান করে তা ব্যবহার করা উচিত । bytebytes.Index()
আইকজা

56
প্রকৃতপক্ষে স্ট্রিং (বাইটআরে) খুব করবে এবং একটি স্লাইস সৃষ্টি সংরক্ষণ করবে
নিক্ষেপ_অপত্তি_ত_আপনি

3
তবে কেবল স্পষ্ট করে বলার জন্য, এটি এমন কোনও কিছুতে বাইটের ক্রম ingালছে যা আশাবাদী একটি বৈধ ইউটিএফ -8 স্ট্রিং (এবং বলবে না, ল্যাটিন -1 ইত্যাদি, বা কিছু ত্রুটিযুক্ত ইউটিএফ -8 ক্রম)। কাস্ট করার সময় গো আপনার জন্য এটি পরীক্ষা করবে না।
ক্যামেরন কের

যদি আপনার বাইট অ্যারেটি বিপরীত ক্রমে হয় তবে ছোট এন্ডিয়ান?
স্যার

374

কি সম্পর্কে?

s := string(byteArray[:])

3
নিশ্চিতভাবে বাইট অ্যারে রূপান্তর করার সবচেয়ে সহজ উপায়। আমি ভাবছি যদি স্ট্রিংস T ট্রিম নাল বাইটগুলি ছড়িয়ে দিতে সহায়তা করবে? golang.org/pkg/strings/#example_Trim
andyvanee

24
প্রশ্নটি বিশেষত বলেছে যে string(byteArray[:])এতে ^@অক্ষর রয়েছে
রবার্ট

24
পার্থক্য কি string(byteArray)? আপনি কেন অ্যারে ব্যবহার করে অনুলিপি করা প্রয়োজন [:]?
রবার্ট জামেবাবা

7
@ রবার্টজারেবা> স্ট্রিং কার্যকরভাবে কেবলমাত্র বাইটের পঠনযোগ্য স্লাইস। আপনি বাইট অ্যারে সরাসরি স্ট্রিংতে রূপান্তর করতে পারবেন না তাই প্রথম টুকরোটি পরে স্ট্রিং করুন।
ফেরহাট এলমাস

3
@RobertZaremba বাইট টুকরা জন্য আপনি যোগ করতে প্রয়োজন হবে না [:], বাইট অ্যারে, আপনি না।
ড্রু লেসুইউর

68

সরলবাদী সমাধান:

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

আমি নিশ্চিত না যদিও এটি কতটা পারফরম্যান্ট।


17

উদাহরণ স্বরূপ,

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

8

নিম্নলিখিত কোডটি '\ 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))
}

শূন্য-বাইটের সন্ধানে সবেমাত্র বায়ার অ্যারে স্ক্যান করার জন্য এটি দ্রুততর হতে পারে, বিশেষত যদি আপনার বেশিরভাগ স্ট্রিং সংক্ষিপ্ত থাকে।


8
আপনার কোডটি সংকলন করে না এবং তা করা সত্ত্বেও, এটি কার্যকর হবে না। একটি বাইনারি অনুসন্ধান অ্যালগরিদম একটি বাছাই করা অ্যারের মধ্যে একটি নির্দিষ্ট মানের অবস্থান খুঁজে পায়। অ্যারে বাছাই করা প্রয়োজন হয় না।
পিটারসো

@ পেটারসো আপনি ঠিকই বলেছেন এবং বাস্তবে এটি কখনই বাছাই করা হয় না কারণ এটি একগুচ্ছ অর্থপূর্ণ নামের প্রতিনিধিত্ব করে।
ডেরিক ঝাং

3
যদি সমস্ত নাল বাইট স্ট্রিংয়ের শেষে হয় তবে একটি বাইনারি অনুসন্ধান কাজ করে।
পল হানকিন

6
ডাউনভোটস আমি বুঝতে পারছি না। কোডটি সংকলন করে এবং সঠিক, স্ট্রিংটির শেষে ব্যতীত no 0 নেই বলে ধরে নেওয়া যায়। কোডটি \ 0 সন্ধান করছে এবং প্রশ্নের অনুমানের অধীনে অ্যারেটিকে 'সাজানো' হিসাবে বিবেচনা করা যেতে পারে, যেহেতু সমস্ত অ-\ 0 সমস্ত \ 0 এর আগে এবং সেগুলিই কোডটি পরীক্ষা করছে। ডাউনভোটাররা যদি উদাহরণটি ইনপুট খুঁজে পেতে পারে যার উপর কোডটি কাজ করে না, তবে আমি উত্তরটি সরিয়ে দেব।
পল হানকিন

1
ইনপুট থাকলে ভুল ফলাফল দেয় []byte{0}। স্লাইসিংয়ের ফলাফল যখন হয় তখন এই ক্ষেত্রে FirstZero()ফিরে আসা উচিত তবে পরিবর্তে এটি প্রত্যাবর্তন করে এবং ফলাফলগুলিতে কাটা কাটা ফলাফল । 0""1"\x00"
আইকজা

3

আপনি যখন অ্যারেতে নন-নীল বাইটের সঠিক দৈর্ঘ্যটি জানেন না, আপনি প্রথমে এটি ছাঁটাই করতে পারেন:

স্ট্রিং (বাইটস.ট্রিম (আরআর, "\ x00"))


1
ক) bytes.Trimএকটি স্লাইস নেয়, একটি অ্যারে নয় (আপনার প্রশ্নের দরকার arr[:]যদি আরার আসলে একটি [100]byteহয় তবে) a খ) bytes.Trimএখানে ব্যবহার করার জন্য ভুল ফাংশন। ইনপুট এর মতো []byte{0,0,'a','b','c',0,'d',0}এটি "" গ এর পরিবর্তে "abc \ x00d" ফিরে আসবে) ইতিমধ্যে একটি সঠিক উত্তর রয়েছে যা ব্যবহার করে bytes.IndexByte, প্রথম শূন্য বাইট খুঁজে পাওয়ার সেরা উপায়।
ডেভ সি

1

কেন এই না?

bytes.NewBuffer(byteArray).String()

1
কারণ ক) প্রশ্নটি আপনাকে একটি অ্যারে বলে তাই আপনার প্রয়োজনের byteArray[:]পরে bytes.NewBufferএকটি গ্রহণ করা হয় []byte; খ) প্রশ্নটি বলেছে যে অ্যারেতে এমন শূন্য রয়েছে যা আপনি মোকাবেলা করেন না; গ) পরিবর্তে যদি আপনার ভেরিয়েবল হ'ল []byte(একমাত্র উপায় আপনার লাইনটি সংকলন করবে) তবে আপনার লাইনটি কেবল একটি ধীর গতিপথ string(v)
ডেভ সি

1

শুধুমাত্র পারফরম্যান্স টিউনিংয়ের জন্য ব্যবহার করুন।

package main

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

func BytesToString(b []byte) string {
    return *(*string)(unsafe.Pointer(&b))
}

func StringToBytes(s string) []byte {
    return *(*[]byte)(unsafe.Pointer(&s))
}

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

1
-1: এটি কোনও গুরুতর উত্তর কিনা তা নিশ্চিত নন তবে আপনি প্রায় নিশ্চিতভাবেই কেবল একটি বাইট টুকরো স্ট্রিংয়ে রূপান্তর করতে প্রতিফলন এবং অনিরাপদ কোডটি চান না
অস্টিন হাইড

1
সতর্কতার একটি শব্দ: বাইট স্লাইসকে একটিতে রূপান্তর করতে অনিরাপদ ব্যবহার করা stringযদি পরে বাইট স্লাইসটি সংশোধন করা হয় তবে গুরুতর জড়িত থাকতে পারে। stringগো-এর মানগুলি অপরিবর্তনীয় হিসাবে সংজ্ঞায়িত করা হয়, যেখানে পুরো গো রানটাইম এবং লাইব্রেরিগুলি তৈরি করে। আপনি যদি এই পথে চলে যান তবে আপনি নিজেকে সবচেয়ে রহস্যময় বাগ এবং রানটাইম ত্রুটির মাঝে নিজেকে টেলিপোর্ট করবেন।
আইজজা

সম্পাদিত, কারণ এটি পয়েন্টার ব্যবহারের বিপরীতে (এটি সরাসরি কাস্টিংয়ের মতো আচরণ করে, অন্য কথায় ফলাফল আবর্জনা সংগ্রহ করা হবে না)। অনুচ্ছেদটি পড়ুন ()) golang.org/pkg/unsafe/#Pointer
লায়েভস ডেক্সটার

0
  • পড়ার জন্য অ্যারের পরিবর্তে স্লাইস ব্যবহার করুন। যেমন 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

ডেটা অন্যের দ্বারা এবং অন্য সি ভাষার দ্বারা লিখিত হয় এবং আমি কেবল এটি পড়তে পেতাম, সুতরাং এটি যেভাবে লেখা হয়েছে তা নিয়ন্ত্রণ করতে পারি না।
ডেরিক ঝাং

1
ওহ, তারপরে দৈর্ঘ্যের মানটি ব্যবহার করে বাইট অ্যারেটি কেটে নিন s := a[:n] বা আপনার s := string(a[:n])যদি স্ট্রিংয়ের প্রয়োজন কেটে নিন। যদি nসরাসরি উপলভ্য না হয় তবে এটি অবশ্যই গণনা করতে হবে, যেমন ড্যানিয়েলের পরামর্শ অনুসারে বাফারে (অ্যারে) নির্দিষ্ট / শূন্য বাইট সন্ধান করে।
zzzz

0

আমি আতঙ্কিত হয়েছি কয়েকবার কয়েকটি পদ্ধতির চেষ্টা করেছি:

রানটাইম ত্রুটি: স্লাইস সীমা ছাড়িয়ে গেছে।

কিন্তু এই অবশেষে কাজ করে।

string(Data[:])


3
এটি বেশি তথ্য যোগ করে না এবং 2013 সাল থেকে মূলত উত্তরটি পুনরাবৃত্তি করে: stackoverflow.com/a/18615786/349333
জোহেম শুলেনক্লাপ্পার

0

যদিও চূড়ান্ত পারফরম্যান্ট না হলেও একমাত্র পঠনযোগ্য সমাধান

  //split by separator and pick the first one. 
  //This has all the characters till null excluding null itself.
  retByteArray := bytes.Split(byteArray[:], []byte{0}) [0]

  // OR 

  //If you want a true C-like string including the null character
  retByteArray := bytes.SplitAfter(byteArray[:], []byte{0}) [0]

সি-স্টাইল বাইট অ্যারে রাখার সম্পূর্ণ উদাহরণ:

package main

import (
    "bytes"
    "fmt"
)

func main() {
    var byteArray = [6]byte{97,98,0,100,0,99}

    cStyleString := bytes.SplitAfter(byteArray[:],  []byte{0}) [0]
    fmt.Println(cStyleString)
}

নালগুলি বাদ দিয়ে গো স্টাইল স্ট্রিংয়ের সম্পূর্ণ উদাহরণ:

package main

import (
    "bytes"
    "fmt"
)

func main() {
    var byteArray = [6]byte{97,98,0,100,0,99}

    goStyleString := string( bytes.Split(byteArray[:],  []byte{0}) [0] )
    fmt.Println(goStyleString)
}

এটি একটি স্লাইস বাইটের স্লাইস বরাদ্দ করে। সুতরাং যদি এটি ভারী বা বারবার ব্যবহৃত হয় তবে পারফরম্যান্সে নজর রাখুন।


-1

এখানে স্ট্রিং-এ বাইট অ্যারে সংকুচিত করার কোড

package main

import (
    "fmt"
)

func main() {
    byteArr := [100]byte{'b', 'y', 't', 'e', 's'}
    firstHalf := ToString(byteArr)
    fmt.Println("Bytes to str", string(firstHalf))
}
func ToString(byteArr [100]byte) []byte {
    arrLen := len(byteArr)
    firstHalf := byteArr[:arrLen/2]
    secHalf := byteArr[arrLen/2:]
    for {
        // if the first element is 0 in secondHalf discard second half
        if len(secHalf) != 0 && secHalf[0] == 0 {
            arrLen = len(firstHalf)
            secHalf = firstHalf[arrLen/2:]
            firstHalf = firstHalf[:arrLen/2]
            continue
        } else {
            for idx := 0; len(secHalf) > idx && secHalf[idx] != 0; idx++ {
                firstHalf = append(firstHalf, secHalf[idx])
            }
        }
        break
    }
    return firstHalf
}

-2

এখানে দ্রুততর উপায়:

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

পরের বার প্রথম প্রশ্ন (এবং বিদ্যমান উত্তর) পড়ুন। (প্লাস, আপনি যদি বাইট স্লাইসটি ব্যবহার fmtকরতে চান তবে এটির fmt.Printf("%s", bytes)চেয়ে দ্রুত প্রিন্ট করতে চান string(bytes))।
ডেভ সি

-7

আমি যখন পুনরাবৃত্তি সমাধান সঙ্গে।

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

আপনি কেন পুনরাবৃত্তি সমাধান পছন্দ করেন?
পিটারসো

পরীক্ষার কেসটি fmt.Println(CToGoString([]byte("ctogo\x00\x00"), "") == "ctogo")প্রিন্ট করা উচিত true, এটি প্রিন্ট করে false
পিটারসো

1
প্রশ্ন জিজ্ঞাসা সবচেয়ে ভাল উপায় কি। এটি যতটা খারাপ তা পেতে পারে: বোঝা শক্ত এবং অত্যন্ত ধীর, এছাড়াও এটি একটি [100]byteকিন্তু একটি রূপান্তর করে না []byte, এবং '\x00'বাইটগুলি সরিয়ে দেয় না । গৃহীত উত্তরের গতির তুলনায় এর গতি (ইনপুট উপর নির্ভর করে) একাধিক ক্রমের মাত্রা দ্বারা ধীর হয়।
আইকজা
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.