2 回答

TA貢獻2003條經驗 獲得超2個贊
enc.NewDecoder()結果是transform.Transformer. 的文檔NewDecoder()說:
轉換不屬于該編碼的源字節本身不會導致錯誤。每個無法轉碼的字節將在輸出中由 '\uFFFD' 的 UTF-8 編碼表示,替換符文。
這告訴我們是讀取器在替換符文(也稱為錯誤符文)上失敗了。幸運的是,很容易將它們剝離出來。
golang.org/x/text/transform提供了兩個輔助函數我們可以用來解決這個問題。Chain()需要一組變壓器并將它們鏈接在一起。RemoveFunc()接受一個函數并過濾掉它返回 true 的所有字節。
類似以下(未經測試)的東西應該可以工作:
filter := transform.Chain(enc.NewDecoder(), transform.RemoveFunc(func (r rune) bool {
return r == utf8.RuneError
}))
r := transform.NewReader(strings.NewReader(body), filter)
這應該過濾掉所有符文錯誤,然后才能到達閱讀器并爆炸。

TA貢獻1797條經驗 獲得超6個贊
這是我采用的解決方案。我沒有使用 Reader,而是手動分配目標緩沖區并Transform()直接調用該函數。當Transform()錯誤出現時,我會檢查一個短的目標緩沖區,并在必要時重新分配。否則我跳過一個符文,假設它是非法字符。為完整起見,我還應該檢查短輸入緩沖區,但在本例中我沒有這樣做。
raw := `So, at 64 kBps, or kilobits per second, you’re getting 8 kilobytes a second.`
enc, _ := charset.Lookup("euc-kr")
dst := make([]byte, len(raw))
d := enc.NewDecoder()
var (
in int
out int
)
for in < len(raw) {
// Do the transformation
ndst, nsrc, err := d.Transform(dst[out:], []byte(raw[in:]), true)
in += nsrc
out += ndst
if err == nil {
// Completed transformation
break
}
if err == transform.ErrShortDst {
// Our output buffer is too small, so we need to grow it
log.Printf("Short")
t := make([]byte, (cap(dst)+1)*2)
copy(t, dst)
dst = t
continue
}
// We're here because of at least one illegal character. Skip over the current rune
// and try again.
_, width := utf8.DecodeRuneInString(raw[in:])
in += width
}
- 2 回答
- 0 關注
- 241 瀏覽
添加回答
舉報