Golang 意外的 EOF

标签 go eof inflate

这是我的代码,我是 Go 的新手。 我试着用谷歌搜索这个问题,但我不能完全理解它。 我认为这与 Read() 方法有关。

package main

import (
    ...
)

type compressor struct {
    content []byte
}

func (r *compressor) compress() []byte {
    ...
}

func (r *compressor) decompress() []byte {
    var buffer bytes.Buffer
    dc := flate.NewReader(&buffer)
    _, err := dc.Read(r.content)
    if err != nil {
        if err != io.EOF {
            log.Fatal(err)
        }
    }

    return buffer.Bytes()
}

func main() {
    fileName := os.Args[1]
    fmt.Println(os.Args)
    contents, err := ioutil.ReadFile(fileName)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Print("Uncompressed data: ")
    fmt.Println(len(contents))

    comp := compressor{contents}
    buffer := comp.decompress()
    fmt.Print("Uncompressed data: ")
    fmt.Println(len(comp.decompress()))

    err = ioutil.WriteFile(fileName+".decjc", buffer, 0644)
    if err != nil {
        log.Fatal(err)
    }
}

这是输出

dylan@skynet:~/Documents/EXP/jc$ ./jc data.txt.jc 
[./jc data.txt.jc]
Uncompressed data: 2364480
2018/06/29 21:41:35 unexpected EOF

最佳答案

在对有问题的特定代码进行跟踪后,我得到了以下答案。

/src/bytes/reader.go 70

func (r *Reader) ReadByte() (byte, error) {
    ...

    if r.i >= int64(len(r.s)) {
        return 0, io.EOF
    }

    ....
}

bytes/reader中有四个可以返回io.EOF的函数,有零个可以返回io.ErrUnexpectedEOF的函数。可以返回io.EOF的四个函数是:

Read(b []byte)
ReadAt(b []byte, off int64)
ReadByte()
ReadRune()

/src/compress/flate/inflate.go 698

func (f *decompressor) moreBits() error {
    c, err := f.r.ReadByte()
    if err != nil {
        return noEOF(err)
    }

    ...
}

在可以返回 io.EOF 的四个函数中,flate/inflate.go 中只有一个函数调用其中任何一个:moreBits() 调用 ReadByte ()

/src/compress/flate/inflate.go 690

func noEOF(e error) error {
    if e == io.EOF {
        return io.ErrUnexpectedEOF
    }

    ...
}

moreBits() 收到错误时,它会调用 noEOF(),检查它是否收到了 io.EOF。如果是这种情况,则返回 io.ErrUnexpectedEOF。一切似乎都按预期工作,而且用户有责任注意这种特殊情况。建议对上面的代码进行编辑以处理似乎已定义的行为:

func (r *compressor) decompress() []byte {
    dc := flate.NewReader(bytes.NewReader(r.content))
    defer dc.Close()
    rb, err := ioutil.ReadAll(dc)
    if err != nil {
        if err != io.EOF && err != io.ErrUnexpectedEOF {
            log.Fatalf("Err %v\n read %v", err, rb)
        }
    }
    return rb
}

这是在 go1.12.9

下检查的

关于Golang 意外的 EOF,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51105792/

相关文章:

postgresql - Gorm卡在gorm.Open上,没有报错但是没有反应

go - 将内容 append 到特定部分中的 Go 模板

c - 为什么我需要多个 EOF (CTRL+Z) 字符?

android - 使用 EditTextPreference 的子类时出现 InstantiationException

go - html/template 中 ParseFiles 函数的不同行为

go - 使用基于字节顺序的Go使用编码/二进制从整数转换为字节数组

c - 使用 "getchar()"和 "EOF"期间出现无意义的输出流

c# - 如何在 C# 中读取二进制文件直到 EOF

android - 如何将 Activity 放入 fragment 中?

visual-studio - 无法膨胀包文件 Visual Studio 错误