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 关注
- 192 浏览
添加回答
举报