0

I've found lots of examples on how to extract all files from .zip, but I can't figure out how to extract a single file without iterating over all files in the .zip file.

Is it possible in Go to extract a single file from a .zip archive without iterating over all files in the .zip file?

For example, if a zip file contained:

folder1/file1.txt
folder1/file2.txt
folder1/file3.txt
folder2/file1.txt

How would I extract only folder2/file1.txt?

Nemo XXX
  • 644
  • 2
  • 14
  • 35
  • 3
    Yes, it's possible. What have you tried? Where did you get stuck? Please include your attempt, aim for a [mcve]. – icza Sep 16 '19 at 11:03
  • I'm using the [ExampleReader](https://golang.org/src/archive/zip/example_test.go) function with an added file name check that breaks the loop if the file name matches `folder2/file1.txt`. What I need to know is how to get the file handle without a loop. – Nemo XXX Sep 16 '19 at 12:06
  • 1
    `zip.Reader` provides you the content of the archive, the files as a slice. There is no helper method to get a file by name, you have to iterate over the files with a loop. You don't need to open / extract the files, but to find a file by name, you have to use a loop. What's wrong with using a loop? – icza Sep 16 '19 at 12:11

1 Answers1

2

zip.Reader provides you the content of the archive, the files as a slice (of zip.File). There is no helper method to get a file by name, you have to iterate over the files with a loop. You don't need to open / extract the files, but to find a file by name, you have to use a loop.

For example:

r, err := zip.OpenReader("testdata/readme.zip")
if err != nil {
    log.Fatal(err)
}
defer r.Close()

for _, f := range r.File {
    if f.Name != "folder2/file1.txt" {
        continue
    }

    // Found it, print its content to terminal:
    rc, err := f.Open()
    if err != nil {
        log.Fatal(err)
    }
    _, err = io.Copy(os.Stdout, rc)
    if err != nil {
        log.Fatal(err)
    }
    rc.Close()
    fmt.Println()
    break
}
icza
  • 389,944
  • 63
  • 907
  • 827