将压缩的 []byte 转换为解压的 []byte 的 Golang 代码。

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

Convert zipped []byte to unzip []byte golang code

问题

我有一个zip文件的[]byte。我需要在不创建新文件的情况下解压它,并获取解压后文件的[]byte。请帮我完成这个任务。

我正在进行一个API调用,得到的响应是以压缩格式的[]byte - 我正在尝试解压它,并使用其内容创建一个新的zip文件。所以是解压 - 重新压缩的过程。

语言:Golang

我使用的代码如下:

func UnzipBytes(zippedBytes []byte) ([]byte, error) {
    reader := bytes.NewReader(zippedBytes)
    zipReader, err := zlib.NewReader(reader)
    if err != nil {
        return nil, err
    }
    defer zipReader.Close()
    p, err := ioutil.ReadAll(zipReader)
    if err != nil {
        return nil, err
    }
    return p, nil
}

我得到一个错误,提示"zlib: invalid header"。

最初用于压缩[]byte的代码如下:

buffer := new(bytes.Buffer)
zipWriter := zip.NewWriter(buffer)
zipFile, err := zipWriter.Create(file.name)
_, err = zipFile.Write(file.content)

[]byte的十六进制转储 - zippedBytes:

00059350  78 b4 5b 0d 2b 81 c2 87  35 76 1b 11 4a ec 07 d1  |x.[.+...5v..J...|
00059360  76 77 a2 e1 3b d9 12 e2  51 d4 c5 bd 4b 2f 09 da  |vw..;...Q...K/..|
00059370  f7 21 c7 26 73 1f 8e da  f0 ff a3 52 f6 e2 00 e6  |.!.&s......R....|

希望对你有所帮助!

英文:

I have []byte of zip file. I have to unzip it without creating a new file, and get a []byte of that unzipped file. Please help me to do that.

I am making an API call and the response I get is the []byte in zipped format - I am trying to unzip it - and use it's content for creating a new zip file. So unzip - rezip.

Language: Golang

Code I've used:

func UnzipBytes(zippedBytes []byte) ([]byte, error) {

	reader := bytes.NewReader(zippedBytes)
	zipReader, err := zlib.NewReader(reader)
	if err != nil {
		return nil, err
	}
	defer zipReader.Close()
	p, err := ioutil.ReadAll(zipReader)
	if err != nil {
		return nil, err
	}
	return p, nil
}

I get an error saying "zlib: invalid header"

The code that was initially used to zip the []byte

buffer := new(bytes.Buffer)
zipWriter := zip.NewWriter(buffer)
zipFile, err := zipWriter.Create(file.name)
_, err = zipFile.Write(file.content)

Hex dump of the []byte - the zippedBytes

00059350  78 b4 5b 0d 2b 81 c2 87  35 76 1b 11 4a ec 07 d1  |x.[.+...5v..J...|
00059360  76 77 a2 e1 3b d9 12 e2  51 d4 c5 bd 4b 2f 09 da  |vw..;...Q...K/..|
00059370  f7 21 c7 26 73 1f 8e da  f0 ff a3 52 f6 e2 00 e6  |.!.&s......R....|

答案1

得分: 1

你使用了zip.Writer来压缩数据。你必须通过调用其Writer.Close()方法来关闭它。你必须使用zip.Reader来读取它,并使用与压缩时相同的名称(file.name)来调用Reader.Open()

以下是示例代码:

func UnzipBytes(name string, zippedBytes []byte) ([]byte, error) {
    reader := bytes.NewReader(zippedBytes)
    zipReader, err := zip.NewReader(reader, int64(len(zippedBytes)))
    if err != nil {
        return nil, err
    }
    f, err := zipReader.Open(name)
    if err != nil {
        panic(err)
    }
    p, err := ioutil.ReadAll(f)
    if err != nil {
        return nil, err
    }
    return p, nil
}

filename := "test.txt"
filecontent := []byte("line1\nline2")

buffer := new(bytes.Buffer)
zipWriter := zip.NewWriter(buffer)
zipFile, err := zipWriter.Create(filename)
if err != nil {
    panic(err)
}
if _, err = zipFile.Write(filecontent); err != nil {
    panic(err)
}
if err = zipWriter.Close(); err != nil {
    panic(err)
}

decoded, err := UnzipBytes(filename, buffer.Bytes())
fmt.Println(err)
fmt.Println(string(decoded))

运行结果(在Go Playground上尝试):

<nil>
line1
line2

如果在解压缩时不知道文件名,你可以查看Reader.Files头字段中的所有文件。你可以选择打开第一个文件:

func UnzipBytes(zippedBytes []byte) ([]byte, error) {
    reader := bytes.NewReader(zippedBytes)
    zipReader, err := zip.NewReader(reader, int64(len(zippedBytes)))
    if err != nil {
        return nil, err
    }
    if len(zipReader.File) == 0 {
        return nil, nil // 没有要打开/提取的文件
    }
    f, err := zipReader.File[0].Open()
    if err != nil {
        panic(err)
    }
    p, err := ioutil.ReadAll(f)
    if err != nil {
        return nil, err
    }
    return p, nil
}

这将输出相同的结果。在Go Playground上尝试这个代码。

英文:

You used zip.Writer to compress the data. You must close it by calling its Writer.Close() method. And you must use zip.Reader to read it, and use Reader.Open() with the same name you used when compressed it (file.name).

This is how it could look like:

func UnzipBytes(name string, zippedBytes []byte) ([]byte, error) {
	reader := bytes.NewReader(zippedBytes)
	zipReader, err := zip.NewReader(reader, int64(len(zippedBytes)))
	if err != nil {
		return nil, err
	}
	f, err := zipReader.Open(name)
	if err != nil {
		panic(err)
	}
	p, err := ioutil.ReadAll(f)
	if err != nil {
		return nil, err
	}
	return p, nil
}

Testing it:

filename := &quot;test.txt&quot;
filecontent := []byte(&quot;line1\nline2&quot;)

buffer := new(bytes.Buffer)
zipWriter := zip.NewWriter(buffer)
zipFile, err := zipWriter.Create(filename)
if err != nil {
	panic(err)
}
if _, err = zipFile.Write(filecontent); err != nil {
	panic(err)
}
if err = zipWriter.Close(); err != nil {
	panic(err)
}

decoded, err := UnzipBytes(filename, buffer.Bytes())
fmt.Println(err)
fmt.Println(string(decoded))

This will output (try it on the Go Playground):

&lt;nil&gt;
line1
line2

If you don't know the name when decompressing, you may see all files in the Reader.Files header field. You may choose to open the first file:

func UnzipBytes(zippedBytes []byte) ([]byte, error) {
	reader := bytes.NewReader(zippedBytes)
	zipReader, err := zip.NewReader(reader, int64(len(zippedBytes)))
	if err != nil {
		return nil, err
	}
	if len(zipReader.File) == 0 {
		return nil, nil // No file to open / extract
	}
	f, err := zipReader.File[0].Open()
	if err != nil {
		panic(err)
	}
	p, err := ioutil.ReadAll(f)
	if err != nil {
		return nil, err
	}
	return p, nil
}

This outputs the same. Try this one on the Go Playground.

huangapple
  • 本文由 发表于 2022年9月14日 21:13:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/73717499.html
匿名

发表评论

匿名网友

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

确定