golang zlib阅读器输出没有被复制到stdout

时间:2015-12-22 15:29:37

标签: go zlib

我已经修改了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
        }
    }

4 个答案:

答案 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)