我一直在处理一些我必须转换为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计划?
答案 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)
}