如何在golang中读取gzip或纯文本阅读器?

时间:2015-02-03 22:28:39

标签: go gzip

我正在golang中编写一个小的webapp,它涉及解析用户上传的文件。我想自动检测文件是否被gzip压缩,并适当地创建读者/扫描仪。一个转折是我无法将整个文件读入内存,我只能在流上操作。这就是我所拥有的:

func scannerFromFile(reader io.Reader) (*bufio.Scanner, error) {

var scanner *bufio.Scanner
//create a bufio.Reader so we can 'peek' at the first few bytes
bReader := bufio.NewReader(reader)

testBytes, err := bReader.Peek(64) //read a few bytes without consuming
if err != nil {
    return nil, err
}
//Detect if the content is gzipped
contentType := http.DetectContentType(testBytes)

//If we detect gzip, then make a gzip reader, then wrap it in a scanner
if strings.Contains(contentType, "x-gzip") {
    gzipReader, err := gzip.NewReader(bReader)
    if (err != nil) {
        return nil, err
    }

    scanner = bufio.NewScanner(gzipReader)

} else {
    //Not gzipped, just make a scanner based on the reader
    scanner = bufio.NewScanner(bReader)
}

return scanner, nil
}

这适用于纯文本,但对于gzip压缩数据,它会错误地膨胀,并且在几kb之后我不可避免地会出现乱码文本。那里有更简单的方法吗?任何想法为什么几千行后它解压不正确?

2 个答案:

答案 0 :(得分:2)

您可以通过检查前2个字节是否等于0x1f8b来检测文件是否已被gziped(我发现信息here)。

在评论中有人提到你应该分别检查这些字节,所以第一个是0x1f,第二个是0x8b

testBytes, err := bReader.Peek(2) //read 2 bytes
....
if testBytes[0] == 31 && testBytes[1] == 139 {
    //gzip
}else{
   ...
}

希望有所帮助。

答案 1 :(得分:0)

谢谢大家 - 结果是twotwotwo和thundercat是正确的,并且流在与我发布的代码无关的地方被破坏了。奇怪的是,它似乎与仍然从请求流中读取时写入http响应有关。我还在调查它,但似乎原来的问题是错误的。