第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

無效字符的字節(jié)到字符串轉(zhuǎn)換

無效字符的字節(jié)到字符串轉(zhuǎn)換

Go
元芳怎么了 2022-10-24 15:52:41
我需要解析可能無效或包含一些錯誤的 UDP 數(shù)據(jù)包。我想用.字節(jié)到字符串轉(zhuǎn)換后替換無效字符,以顯示數(shù)據(jù)包的內(nèi)容。我該怎么做?這是我的代碼:func main() {   a := []byte{'a', 0xff, 0xaf, 'b', 0xbf}   s := string(a)   s = strings.Replace(s, string(0xFFFD), ".", 0)   fmt.Println("s: ", s) // I would like to display "a..b."   for _, r := range s {      fmt.Println("r: ", r)   }   rs := []rune(s)   fmt.Println("rs: ", rs)}
查看完整描述

3 回答

?
交互式愛情

TA貢獻(xiàn)1712條經(jīng)驗 獲得超3個贊

您的方法的根本問題是類型轉(zhuǎn)換[]byte為的結(jié)果中string沒有任何U+FFFDs :此類型轉(zhuǎn)換僅將字節(jié)從源逐字復(fù)制到目標(biāo)。
就像字節(jié)切片一樣,Go 中的字符串沒有義務(wù)包含 UTF-8 編碼的文本;它們可以包含任何數(shù)據(jù),包括與文本無關(guān)的不透明二進(jìn)制數(shù)據(jù)。

但是對字符串的一些操作——即將它們類型轉(zhuǎn)換為[]rune使用它們迭代range——確實將字符串解釋為 UTF-8 編碼的文本。這正是你被絆倒的地方:你的range調(diào)試循環(huán)試圖解釋字符串,每次解碼正確編碼的代碼點的嘗試失敗時,都會range產(chǎn)生一個替換字符,U+FFFD.
重申一下,通過類型轉(zhuǎn)換獲得的字符串不包含您希望被正則表達(dá)式替換的字符。

至于如何從您的數(shù)據(jù)中實際生成有效的 UTF-8 編碼字符串,您可以采用兩步過程:

  1. 將你的字節(jié)切片類型轉(zhuǎn)換為字符串——就像你已經(jīng)做的那樣。

  2. 使用任何將字符串解釋為 UTF-8 的方法——替換將在此過程中動態(tài)出現(xiàn)的 U+FFFD——在您進(jìn)行迭代時。

像這樣的東西:

var sb strings.Builder

for _, c := range string(b) {

  if c == '\uFFFD' {

    sb.WriteByte('.')

  } else {

    sb.WriteRune(c)

  }

}

return sb.String()

關(guān)于性能的說明:由于將 a 類型轉(zhuǎn)換[]byte為string復(fù)制內(nèi)存——因為字符串是不可變的,而切片不是——類型轉(zhuǎn)換的第一步可能會浪費處理大量數(shù)據(jù)和/或緊密工作的代碼的資源處理循環(huán)。

在這種情況下,可能值得使用適用于字節(jié)片的包的DecodeRune功能。encoding/utf8它的文檔中的一個例子可以很容易地適應(yīng)上面的循環(huán)。



查看完整回答
反對 回復(fù) 2022-10-24
?
湖上湖

TA貢獻(xiàn)2003條經(jīng)驗 獲得超2個贊

您可能希望strings.ToValidUTF8()用于此:


ToValidUTF8 返回字符串 s 的副本,其中每次運行無效的 UTF-8 字節(jié)序列都被替換字符串替換,該替換字符串可能為空。


它“似乎”完全符合您的需要。測試它:


a := []byte{'a', 0xff, 0xaf, 'b', 0xbf}

s := strings.ToValidUTF8(string(a), ".")

fmt.Println(s)

輸出(在Go Playground上試試):


a.b.

我寫“貌似”是因為如您所見,a和b: 之間只有一個點,因為可能有 2 個字節(jié),但有一個無效序列。


請注意,您可以避免[]byte=>string轉(zhuǎn)換,因為有一個bytes.ToValidUTF8()等價的操作并返回 a []byte:


a := []byte{'a', 0xff, 0xaf, 'b', 0xbf}

a = bytes.ToValidUTF8(a, []byte{'.'})

fmt.Println(string(a))

輸出將是相同的。在Go Playground上試試這個。


如果您對多個(無效序列)字節(jié)可能會縮小為一個點感到困擾,請繼續(xù)閱讀。


另請注意,要檢查可能包含或不包含文本的任意字節(jié)切片,您可以簡單地使用hex.Dump()which 生成如下輸出:


a := []byte{'a', 0xff, 0xaf, 'b', 0xbf}

fmt.Println(hex.Dump(a))

輸出:


00000000  61 ff af 62 bf                                    |a..b.|

您的預(yù)期輸出a..b.包含其他(有用的)數(shù)據(jù),例如十六進(jìn)制偏移量和字節(jié)的十六進(jìn)制表示。


要獲得“更好”的輸出圖片,請嘗試使用更長的輸入:


a = []byte{'a', 0xff, 0xaf, 'b', 0xbf, 50: 0xff}

fmt.Println(hex.Dump(a))


00000000  61 ff af 62 bf 00 00 00  00 00 00 00 00 00 00 00  |a..b............|

00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|

00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|

00000030  00 00 ff                                          |...|


查看完整回答
反對 回復(fù) 2022-10-24
?
慕桂英4014372

TA貢獻(xiàn)1871條經(jīng)驗 獲得超13個贊

并且非常清楚地解釋了從字符串中掃描 unicode 符文的問題。


只需添加以下注釋:如果您的意圖是僅查看 ASCII 范圍內(nèi)的字符(可打印字符 < 127)并且您并不真正關(guān)心其他 unicode 代碼點,您可以更直率:


// create a byte slice with the same byte length as s

var bs = make([]byte, len(s))


// scan s byte by byte :

for i := 0; i < len(s); i++ {

    switch {

    case 32 <= s[i] && s[i] <= 126:

        bs[i] = s[i]


    // depending on your needs, you may also keep characters in the 0..31 range,

    // like 'tab' (9), 'linefeed' (10) or 'carriage return' (13) :

    // case s[i] == 9, s[i] == 10, s[i] == 13:

    //   bs[i] = s[i]


    default:

        bs[i] = '.'

    }

}



fmt.Printf("rs: %s\n", bs)



這個功能會給你一些接近“文本”部分的東西hexdump -C。


查看完整回答
反對 回復(fù) 2022-10-24
  • 3 回答
  • 0 關(guān)注
  • 148 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學(xué)習(xí)伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號