我已经修改了zlib包的官方文档示例,以使用打开的文件而不是一组硬编码字节(下面的代码)。
代码读取源文本文件的内容并使用zlib包压缩它。然后我尝试回读压缩文件并将其解压缩的内容打印到stdout。
代码没有错误,但它也没有按照我的预期去做;这是将解压缩的文件内容显示到stdout中。
另外:是否有另一种显示此信息的方式,而不是使用
io.Copy
?
package main
import (
"compress/zlib"
"io"
"log"
"os"
)
func main() {
var err error
// This defends against an error preventing `defer` from being called
// As log.Fatal otherwise calls `os.Exit`
defer func() {
if err != nil {
log.Fatalln("\nDeferred log: \n", err)
}
}()
src, err := os.Open("source.txt")
if err != nil {
return
}
defer src.Close()
dest, err := os.Create("new.txt")
if err != nil {
return
}
defer dest.Close()
zdest := zlib.NewWriter(dest)
defer zdest.Close()
if _, err := io.Copy(zdest, src); err != nil {
return
}
n, err := os.Open("new.txt")
if err != nil {
return
}
r, err := zlib.NewReader(n)
if err != nil {
return
}
defer r.Close()
io.Copy(os.Stdout, r)
err = os.Remove("new.txt")
if err != nil {
return
}
}
答案 0 :(得分:2)
我认为你把所有这些defer
内容和你的“技巧”错误检查搞砸了代码逻辑。
刷新或关闭时最终会写入文件。您只需复制到new.txt而不关闭它,然后再打开它来阅读它。
在具有多个出口的函数内推迟关闭文件:确保在保留函数后文件关闭。但是你的主要要求在复制之后关闭new.txt,然后重新打开它。所以不要在这里推迟关闭。
顺便说一句:你对log.Fatal的防御终止代码而不打电话给你的推迟,至少是奇怪的。操作系统将文件全部置于适当的状态,完全没有必要使这样的东西复杂化。
答案 1 :(得分:2)
您的defer
func没有做任何事情,因为您在每个新作业上都隐藏了err
变量。如果要运行defer
,请从单独的函数返回,并在return语句后调用log.Fatal
。
至于为什么你没有看到任何输出,这是因为你推迟了所有的Close调用。在函数退出之前,zlib.Writer
不会被刷新,目标文件也不会被刷新。在您需要的地方明确地致电Close()
。
zdest := zlib.NewWriter(dest)
if _, err := io.Copy(zdest, src); err != nil {
log.Fatal(err)
}
zdest.Close()
dest.Close()
答案 2 :(得分:1)
检查第二个Copy
:
2015/12/22 19:00:33
Deferred log:
unexpected EOF
exit status 1
问题是,您需要在完成写作后立即关闭zdest
。在第一个Copy
之后关闭它并且它可以正常工作。
答案 3 :(得分:1)
我建议使用io.MultiWriter。 这样你只能从src中读取一次。对于小文件来说收益不大,但对于较大的文件来说速度更快
w := io.MultiWriter(dest, os.Stdout)