如何在Go中改进文件编码转换

时间:2018-06-14 15:08:47

标签: python go encoding io character-encoding

我一直在处理一些我必须转换为UTF-8的大文件,因为像iconv这样的巨大传统工具无法正常工作。所以我决定在Go中编写自己的工具,但是我注意到Go中的这种编码转换非常慢。这是我的代码:

package main

import (
    "fmt"
    "io"
    "log"
    "os"

    "golang.org/x/text/encoding/charmap"
)

func main() {
    if len(os.Args) != 3 {
        fmt.Fprintf(os.Stderr, "usage:\n\t%s [input] [output]\n", os.Args[0])
        os.Exit(1)
    }

    f, err := os.Open(os.Args[1])

    if err != nil {
        log.Fatal(err)
    }

    out, err := os.Create(os.Args[2])

    if err != nil {
        log.Fatal(err)
    }

    r := charmap.ISO8859_1.NewDecoder().Reader(f)

    buf := make([]byte, 1048576)

    io.CopyBuffer(out, r, buf)

    out.Close()
    f.Close()
}

Python中的类似代码更高效:

import codecs
BLOCKSIZE = 1048576 # or some other, desired size in bytes
with codecs.open("FRWAC-01.xml", "r", "latin_1") as sourceFile:
    with codecs.open("FRWAC-01-utf8.xml", "w", "utf-8") as targetFile:
        while True:
            contents = sourceFile.read(BLOCKSIZE)
            if not contents:
                break
            targetFile.write(contents)

我确信我的Go代码会更快,因为Go中的I / O速度很快,但事实证明它比Python代码慢得多。有没有办法改进Go计划?

1 个答案:

答案 0 :(得分:4)

这里的问题是您在两种情况下都没有比较相同的代码。 Go中的IO速度也不会与python显着不同,因为它们正在进行相同的系统调用。

在python版本中,默认情况下缓冲文件。在Go版本中,当您使用带有io.CopyBuffer字节缓冲区的1048576时,解码器将直接在无缓冲文件上进行任何大小Read调用。< / p>

使用bufio包装文件IO将产生可比较的结果。

inFile, err := os.Open(os.Args[1])
if err != nil {
    log.Fatal(err)
}
defer inFile.Close()

outFile, err := os.Create(os.Args[2])
if err != nil {
    log.Fatal(err)
}
defer outFile.Close()

in := bufio.NewReaderSize(inFile, 1<<20)

out := bufio.NewWriterSize(outFile, 1<<20)
defer out.Flush()

r := charmap.ISO8859_1.NewDecoder().Reader(in)

if _, err := io.Copy(out, r); err != nil {
    log.Fatal(err)
}