go - 用 Go 解码文本时忽略非法字节?

标签 go character-encoding

我正在转换一个用于解码电子邮件的 Go 程序。它当前运行 iconv 来进行实际的解码,这当然有开销。我想使用 golang.org/x/text/transform 和 golang.org/x/net/html/charset 包来执行此操作。这是工作代码:

// cs is the charset that the email body is encoded with, pulled from
// the Content-Type declaration.
enc, name := charset.Lookup(cs)
if enc == nil {
    log.Fatalf("Can't find %s", cs)
}
// body is the email body we're converting to utf-8
r := transform.NewReader(strings.NewReader(body), enc.NewDecoder())

// result contains the converted-to-utf8 email body
result, err := ioutil.ReadAll(r)

除非遇到非法字节,否则效果很好,不幸的是,在野外处理电子邮件时,这种情况并不少见。 ioutil.ReadAll() 返回错误以及出现问题之前的所有转换字节。有没有办法告诉转换包忽略非法字节?现在,我们使用 iconv 的 -c 标志来做到这一点。我已经浏览了转换包的文档,但我不知道它是否可能。

更新: 这是一个显示问题的测试程序(Go Playground 没有字符集或转换包...)。原始文本取自真实的电子邮件。是的,它是英文的,是的,电子邮件中的字符集设置为 EUC-KR。我需要它来忽略那个撇号。

package main

import (
    "io/ioutil"
    "log"
    "strings"

    "golang.org/x/net/html/charset"
    "golang.org/x/text/transform"
)

func main() {
    raw := `So, at 64 kBps, or kilobits per second, you’re getting 8 kilobytes a second.`
    enc, _ := charset.Lookup("euc-kr")
    r := transform.NewReader(strings.NewReader(raw), enc.NewDecoder())
    result, err := ioutil.ReadAll(r)
    if err != nil {
        log.Printf("ReadAll returned %s", err)
    }
    log.Printf("RESULT: '%s'", string(result))
}

最佳答案

enc.NewDecoder() 结果是 transform.TransformerNewDecoder() 的文档说:

Transforming source bytes that are not of that encoding will not result in an error per se. Each byte that cannot be transcoded will be represented in the output by the UTF-8 encoding of '\uFFFD', the replacement rune.

这告诉我们读取器在替换 rune (也称为错误 rune )上失败。幸运的是,很容易将它们删除。

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)

这应该在所有 rune 错误到达阅读器并爆炸之前过滤掉它们。

关于go - 用 Go 解码文本时忽略非法字节?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32512500/

相关文章:

struct - 有没有办法强制转换结构以通过 channel 发送

java - 调试 MySQL 字符集错误

go - 如何在 Go 中编译程序

google-app-engine - 使用 Go 管理和包含多个文件的最佳方法是什么?

json - 我无法解析 Go 中的日期/时间 - Gin

java - 字节到字符串,反之亦然

php - MySQL incorrect string value 错误在 MySQL 5.7 但不是在 5.5

go - 电子邮件主题、标题在不同字符集中解码,如 ISO-2022-JP、GB-2312 等

java - Java字符集-如何从System.in获得正确的输入?

go - 在 Negroni 下找不到路由时提供索引文件