Пакет archive/zip

Пакет archive/zip предоставляет функции для работы с ZIP-архивами. С его помощью можно создавать новые архивы, добавлять в них файлы, а также читать и извлекать содержимое существующих архивов. Основными типами пакета являются Writer для создания архивов и Reader для чтения архивов.

Создание ZIP-архива

Для создания ZIP-архива используется тип Writer. Функция zip.NewWriter создает новый экземпляр для записи в файл или в любой другой поток.

Синтаксис

gofunc NewWriter(w io.Writer) *zip.Writer

Функция NewWriter принимает интерфейс io.Writer и возвращает указатель на zip.Writer.

Пример

Создадим ZIP-архив и добавим в него два файла:

gopackage main

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

func main() {
  buf := new(bytes.Buffer)
  zipWriter := zip.NewWriter(buf)

  file1, err := zipWriter.Create("file1.txt")
  if err != nil {
    fmt.Println(err)
    return
  }
  _, err = file1.Write([]byte("Content of file 1"))
  if err != nil {
    fmt.Println(err)
    return
  }

  file2, err := zipWriter.Create("file2.txt")
  if err != nil {
    fmt.Println(err)
    return
  }
  _, err = file2.Write([]byte("Content of file 2"))
  if err != nil {
    fmt.Println(err)
    return
  }

  err = zipWriter.Close()
  if err != nil {
    fmt.Println(err)
    return
  }

  fmt.Printf("Archive size: %d bytes", buf.Len())
}

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

go"Archive size: 232 bytes"

Метод Create создает новый файл в архиве и возвращает интерфейс io.Writer для записи его содержимого. После добавления всех файлов необходимо вызвать метод Close, чтобы завершить запись архива.

Чтение ZIP-архива

Для чтения ZIP-архива используется функция zip.OpenReader, которая открывает архив из файла, или функция zip.NewReader, которая читает архив из байтового потока.

Синтаксис

gofunc OpenReader(name string) (*zip.ReadCloser, error)
func NewReader(r io.ReaderAt, size int64) (*zip.Reader, error)

Функция OpenReader принимает имя файла и возвращает указатель на zip.ReadCloser, который нужно закрыть после использования. Функция NewReader принимает интерфейс io.ReaderAt и размер архива.

Пример

Прочитаем архив из байтового буфера и выведем список файлов:

gopackage main

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

func main() {
  buf := new(bytes.Buffer)
  zipWriter := zip.NewWriter(buf)

  file, _ := zipWriter.Create("file1.txt")
  file.Write([]byte("Content"))
  zipWriter.Close()

  zipReader, err := zip.NewReader(bytes.NewReader(buf.Bytes()), int64(buf.Len()))
  if err != nil {
    fmt.Println(err)
    return
  }

  for _, file := range zipReader.File {
    fmt.Println(file.Name)
  }
}

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

go"file1.txt"

Извлечение файлов из архива

Для извлечения файла из архива необходимо открыть его с помощью метода Open и прочитать содержимое.

Синтаксис

gofunc (f *File) Open() (io.ReadCloser, error)

Метод Open возвращает интерфейс io.ReadCloser для чтения содержимого файла.

Пример

Извлечем файл из архива и выведем его содержимое:

gopackage main

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

func main() {
  buf := new(bytes.Buffer)
  zipWriter := zip.NewWriter(buf)
  file, _ := zipWriter.Create("data.txt")
  file.Write([]byte("Hello, World!"))
  zipWriter.Close()

  zipReader, _ := zip.NewReader(bytes.NewReader(buf.Bytes()), int64(buf.Len()))

  for _, f := range zipReader.File {
    reader, err := f.Open()
    if err != nil {
      fmt.Println(err)
      continue
    }
    defer reader.Close()

    content, err := io.ReadAll(reader)
    if err != nil {
      fmt.Println(err)
      continue
    }
    fmt.Printf("%s: %s", f.Name, string(content))
  }
}

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

go"data.txt: Hello, World!"

Добавление файлов с настройками

Для более тонкой настройки добавляемых файлов используется метод CreateHeader, который позволяет задать метаданные файла, такие как время модификации и права доступа.

Синтаксис

gofunc (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error)

Метод CreateHeader принимает указатель на структуру FileHeader и возвращает интерфейс для записи содержимого.

Пример

Добавим файл с пользовательскими метаданными:

gopackage main

import (
  "archive/zip"
  "bytes"
  "fmt"
  "time"
)

func main() {
  buf := new(bytes.Buffer)
  zipWriter := zip.NewWriter(buf)

  header := &zip.FileHeader{
    Name:   "config.json",
    Method:   zip.Deflate,
    Modified: time.Now(),
  }
  writer, err := zipWriter.CreateHeader(header)
  if err != nil {
    fmt.Println(err)
    return
  }
  _, err = writer.Write([]byte(`{"key": "value"}`))
  if err != nil {
    fmt.Println(err)
    return
  }

  zipWriter.Close()
  fmt.Printf("Archive created, size: %d bytes", buf.Len())
}

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

go"Archive created, size: 113 bytes"

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

  • тип zip.Writer,
    который используется для создания ZIP-архивов
  • тип zip.Reader,
    который используется для чтения ZIP-архивов
  • тип zip.File,
    который представляет отдельный файл в архиве
  • функцию zip.OpenReader,
    которая открывает ZIP-архив из файла