Тип zip.Reader

Тип zip.Reader представляет собой читателя ZIP-архива, который позволяет получить доступ к файлам внутри архива. Он содержит поле File — слайс структур zip.File, каждая из которых описывает один файл или директорию в архиве. Для создания zip.Reader используется функция zip.NewReader, которая принимает io.ReaderAt и размер архива в байтах.

Создание Reader

Для создания читателя архива необходимо открыть ZIP-файл с помощью os.Open, получить его статистику и передать данные в zip.NewReader:

gopackage main

import (
  "archive/zip"
  "fmt"
  "io"
  "os"
)

func main() {
  file, err := os.Open("archive.zip")
  if err != nil {
    fmt.Println("Error opening file:", err)
    return
  }
  defer file.Close()

  info, err := file.Stat()
  if err != nil {
    fmt.Println("Error getting file info:", err)
    return
  }

  reader, err := zip.NewReader(file, info.Size())
  if err != nil {
    fmt.Println("Error creating zip reader:", err)
    return
  }

  fmt.Printf("Archive has %d files\n", len(reader.File))
}

Результат выполнения кода:

go"Archive has 3 files"

Чтение содержимого файла

Для чтения конкретного файла из архива необходимо получить zip.File из слайса File и вызвать метод Open, который возвращает io.ReadCloser для чтения данных:

gopackage main

import (
  "archive/zip"
  "fmt"
  "io"
  "os"
)

func main() {
  file, err := os.Open("archive.zip")
  if err != nil {
    fmt.Println("Error opening file:", err)
    return
  }
  defer file.Close()

  info, err := file.Stat()
  if err != nil {
    fmt.Println("Error getting file info:", err)
    return
  }

  reader, err := zip.NewReader(file, info.Size())
  if err != nil {
    fmt.Println("Error creating zip reader:", err)
    return
  }

  for _, f := range reader.File {
    fmt.Printf("File: %s, Size: %d bytes\n", f.Name, f.UncompressedSize64)

    if f.Name == "example.txt" {
      rc, err := f.Open()
      if err != nil {
        fmt.Println("Error opening file:", err)
        continue
      }
      defer rc.Close()

      data, err := io.ReadAll(rc)
      if err != nil {
        fmt.Println("Error reading file:", err)
        continue
      }
      fmt.Printf("Content: %s\n", string(data))
    }
  }
}

Результат выполнения кода:

go"File: example.txt, Size: 12 bytes"
"Content: Hello, World!"
"File: data.bin, Size: 1024 bytes"

Перебор всех файлов в архиве

Слайс File содержит все элементы архива, включая директории. Для перебора всех файлов можно использовать цикл for range. Обратите внимание, что имена файлов содержат путь относительно корня архива:

gopackage main

import (
  "archive/zip"
  "fmt"
  "os"
)

func main() {
  file, err := os.Open("archive.zip")
  if err != nil {
    fmt.Println("Error opening file:", err)
    return
  }
  defer file.Close()

  info, err := file.Stat()
  if err != nil {
    fmt.Println("Error getting file info:", err)
    return
  }

  reader, err := zip.NewReader(file, info.Size())
  if err != nil {
    fmt.Println("Error creating zip reader:", err)
    return
  }

  for i, f := range reader.File {
    isDir := f.FileInfo().IsDir()
    fmt.Printf("[%d] %s (dir: %v, size: %d bytes)\n",
      i, f.Name, isDir, f.UncompressedSize64)
  }
}

Результат выполнения кода:

go"[0] docs/ (dir: true, size: 0 bytes)"
"[1] docs/readme.txt (dir: false, size: 28 bytes)"
"[2] config.json (dir: false, size: 156 bytes)"

Смотрите также

  • функцию zip.NewReader,
    которая создаёт zip.Reader из произвольного источника
  • тип zip.File,
    представляющий отдельный файл внутри архива
  • функцию zip.OpenReader,
    которая открывает ZIP-файл по пути и возвращает ReadCloser
  • метод zip.File.Open,
    который открывает файл для чтения его содержимого