这是我的代码,我是Go的新手。
我曾尝试使用Google搜索该问题,但我对此一无所知。
我认为这与Read()方法有关。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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)
    }
}

这是输出

1
2
3
4
[email protected]:~/Documents/EXP/jc$ ./jc data.txt.jc
[./jc data.txt.jc]
Uncompressed data: 2364480
2018/06/29 21:41:35 unexpected EOF
  • 错误在哪里抛出? 什么线
  • 您正在从一个空的缓冲区读取数据,因此无需解压缩。
  • 缓冲区实际上确实包含内容
  • 也许您在decompress()中的第一行表示bytes.NewReader(r.content)
  • @Dylan:不,不是。 您正在读取buffer,它是一个bytes.Buffer,您从未将任何数据放入其中。
  • 再看看io.Reader.Read。 它读入它的论点,而不是它。 它从何处读取完全取决于实现。 读者从您传递给NewReader的东西中读取内容。
  • 请看看这个Github问题评论:github.com/revel/revel/issues/566#issuecomment-42019967

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

/src/bytes/reader.go 70

1
2
3
4
5
6
7
8
9
func (r *Reader) ReadByte() (byte, error) {
    ...

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

    ....
}

字节/读取器中有四个函数可以返回io.EOF,而零个函数可以返回io.ErrUnexpectedEOF。可以返回io.EOF的四个函数是:

1
2
3
4
Read(b []byte)
ReadAt(b []byte, off int64)
ReadByte()
ReadRune()

/src/compress/flate/inflate.go 698

1
2
3
4
5
6
7
8
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

1
2
3
4
5
6
7
func noEOF(e error) error {
    if e == io.EOF {
        return io.ErrUnexpectedEOF
    }

    ...
}

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

1
2
3
4
5
6
7
8
9
10
11
12
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\
 read %v", err, rb)
        }
    }
    return rb
}

go1.12.9下对此进行了检查

  • 我在测试中遇到了这个问题,您的解决方案在那里工作。 我不认为这是对的,但是对于测试,我可以有一些这样的技巧。

您进入了,输出混合了。

flate.NewReader将压缩的输入作为io.Reader,并返回一个io.ReadCloser,可用于获取未压缩的输出:

1
2
3
4
5
6
7
8
9
10
11
12
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 {
            log.Fatalf("Err %v\
 read %v", err, rb)
        }
    }
    return rb
}
  • 读入一个空字节片是徒劳的。 您可能是说ioutil.ReadAll左右。
  • 我发现,另一件事是压缩时编码出现问题。 因此,在解压缩时,其中一个字节将解码为EOF。
  • 请注意,compressflate不会解压缩gzip文件。 有compressgzip