从文件中读取全部内容不如预期那样工作。

huangapple go评论88阅读模式
英文:

ReadAll from File not working as Expected

问题

我正在尝试创建一个临时的gzip文件并将数据写入文件。问题是我不理解ReadAll的工作原理。我期望ReadAll返回写入文件的字节...但实际上没有返回任何字节。然而,File.Stat命令显示确实有数据。

以下是代码的翻译:

filename := "test"
file, err := ioutil.TempFile("", filename)
if err != nil {
    fmt.Println(err)
}
defer func() {
    if err := os.Remove(file.Name()); err != nil {
        fmt.Println(err)
    }
}()

w := gzip.NewWriter(file)
_, err = w.Write([]byte("hell0"))
if err != nil {
    fmt.Println(err)
}

fileInfo, err := file.Stat()
if err != nil {
    fmt.Println(err)
}
fileBytes, err := ioutil.ReadAll(file)
if err != nil {
    fmt.Println(err)
}
if err := w.Close(); err != nil {
    fmt.Println(err)
}
fmt.Println("SIZE1:", fileInfo.Size())
fmt.Println("SIZE2:", len(fileBytes))

为什么没有返回字节?
如何获取返回的字节?

英文:

I am trying to create a temporary gzip file and write to the file. The problem is that I am not understanding what is going on with ReadAll. I expected ReadAll to return the bytes written to the file... however there are none. Yet the File.Stat command shows that there is indeed data.

filename := "test"
file, err := ioutil.TempFile("", filename)
if err != nil {
	fmt.Println(err)
}
defer func() {
	if err := os.Remove(file.Name()); err != nil {
		fmt.Println(err)
	}
}()

w := gzip.NewWriter(file)
_, err = w.Write([]byte("hell0"))
if err != nil {
	fmt.Println(err)
}

fileInfo, err := file.Stat()
if err != nil {
	fmt.Println(err)
}
fileBytes, err := ioutil.ReadAll(file)
if err != nil {
	fmt.Println(err)
}
if err := w.Close(); err != nil {
	fmt.Println(err)
}
fmt.Println("SIZE1:", fileInfo.Size())
fmt.Println("SIZE2:", len(fileBytes))

Here is a playground link https://play.golang.org/p/zX8TSCAbRL

Why are there no returned bytes?
How do I get the returned bytes?

答案1

得分: 3

在读取文件之前关闭它。

根据gzip的文档

Write将p的压缩形式写入底层的io.Writer。压缩的字节不一定会在Writer关闭之前刷新。

因此,在尝试读取字节数之前,需要同时关闭gzip Writer和底层的io.Writer。

func main() {
    basename := "test"
    file, err := ioutil.TempFile("", basename)
    tempFilename := file.Name()
    if err != nil {
        fmt.Println(err)
    }
    defer func() {
        if err := os.Remove(file.Name()); err != nil {
            fmt.Println(err)
        }
    }()

    w := gzip.NewWriter(file)
    _, err = w.Write([]byte("hell0"))
    if err != nil {
        fmt.Println(err)
    }

    w.Close()
    file.Close()

    file, err = os.Open(tempFilename)
    fileInfo, err := file.Stat()
    if err != nil {
        fmt.Println(err)
    }
    fileBytes, err := ioutil.ReadAll(file)
    if err != nil {
        fmt.Println(err)
    }
    if err := w.Close(); err != nil {
        fmt.Println(err)
    }
    fmt.Println("SIZE1:", fileInfo.Size())
    fmt.Println("SIZE2:", len(fileBytes))
}

Playground上查看

英文:

Close the file before reading it.

From the documentation of gzip:

> Write writes a compressed form of p to the underlying io.Writer. The compressed bytes are not necessarily flushed until the Writer is closed.

The solution therefore is to Close both the gzip Writer as well as the underlying io.Writer before attempting to read the number of bytes.

	func main() {
		basename := "test"
		file, err := ioutil.TempFile("", basename)
		tempFilename := file.Name()
		if err != nil {
			fmt.Println(err)
		}
		defer func() {
			if err := os.Remove(file.Name()); err != nil {
				fmt.Println(err)
			}
		}()

		w := gzip.NewWriter(file)
		_, err = w.Write([]byte("hell0"))
		if err != nil {
			fmt.Println(err)
		}

		w.Close()
		file.Close()

		file, err = os.Open(tempFilename)
		fileInfo, err := file.Stat()
		if err != nil {
			fmt.Println(err)
		}
		fileBytes, err := ioutil.ReadAll(file)
		if err != nil {
			fmt.Println(err)
		}
		if err := w.Close(); err != nil {
			fmt.Println(err)
		}
		fmt.Println("SIZE1:", fileInfo.Size())
		fmt.Println("SIZE2:", len(fileBytes))

}

View on Playground.

答案2

得分: 1

你必须seek文件的开头:

_, _ = file.Seek(0, 0)
fileBytes, err := ioutil.ReadAll(file)
if err != nil {
	fmt.Println(err)
}

请查看Playground

英文:

Yo must seek the start of the file:

_, _ = file.Seek(0, 0)
fileBytes, err := ioutil.ReadAll(file)
if err != nil {
	fmt.Println(err)
}

Check the Playground

huangapple
  • 本文由 发表于 2017年3月3日 06:31:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/42567262.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定