Тип tar.Reader

Тип tar.Reader предоставляет методы для последовательного чтения файлов из TAR-архива. Он создается с помощью функции tar.NewReader, которая принимает на вход io.Reader - источник данных архива. Основной метод Next переходит к следующему файлу в архиве и возвращает информацию о нем в виде tar.Header.

Синтаксис

gotype Reader struct {
  // содержит скрытые поля
}

func NewReader(r io.Reader) *Reader
func (tr *Reader) Next() (*Header, error)
func (tr *Reader) Read(b []byte) (int, error)

Пример

Давайте создадим TAR-архив из двух файлов и прочитаем его:

gopackage main

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

func main() {
  var buf bytes.Buffer
  tw := tar.NewWriter(&buf)
  
  // Создаем два файла в архиве
  headers := []struct {
    name string
    body string
  }{
    {"file1.txt", "Hello, World!"},
    {"file2.txt", "Second file content"},
  }
  
  for _, h := range headers {
    err := tw.WriteHeader(&tar.Header{
      Name: h.name,
      Mode: 0644,
      Size: int64(len(h.body)),
    })
    if err != nil {
      panic(err)
    }
    _, err = tw.Write([]byte(h.body))
    if err != nil {
      panic(err)
    }
  }
  tw.Close()
  
  // Читаем созданный архив
  tr := tar.NewReader(&buf)
  for {
    header, err := tr.Next()
    if err == io.EOF {
      break
    }
    if err != nil {
      panic(err)
    }
    
    fmt.Printf("File: %s, Size: %d\n", header.Name, header.Size)
    
    data := make([]byte, header.Size)
    _, err = tr.Read(data)
    if err != nil && err != io.EOF {
      panic(err)
    }
    fmt.Printf("Content: %s\n", string(data))
  }
}

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

go"File: file1.txt, Size: 13"
"Content: Hello, World!"
"File: file2.txt, Size: 20"
"Content: Second file content"

Пример

Прочитаем только один конкретный файл из архива:

gopackage main

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

func main() {
  var buf bytes.Buffer
  tw := tar.NewWriter(&buf)
  
  err := tw.WriteHeader(&tar.Header{
    Name: "data.txt",
    Mode: 0644,
    Size: 12,
  })
  if err != nil {
    panic(err)
  }
  _, err = tw.Write([]byte("sample data"))
  if err != nil {
    panic(err)
  }
  tw.Close()
  
  tr := tar.NewReader(&buf)
  targetFile := "data.txt"
  found := false
  
  for {
    header, err := tr.Next()
    if err == io.EOF {
      break
    }
    if err != nil {
      panic(err)
    }
    
    if header.Name == targetFile {
      data := make([]byte, header.Size)
      tr.Read(data)
      fmt.Printf("Found %s: %s\n", targetFile, string(data))
      found = true
      break
    }
  }
  
  if !found {
    fmt.Printf("File %s not found\n", targetFile)
  }
}

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

go"Found data.txt: sample data"

Пример

Обработаем ошибки при чтении поврежденного архива:

gopackage main

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

func main() {
  // Создаем некорректный TAR-архив
  invalidData := []byte("invalid tar data")
  tr := tar.NewReader(bytes.NewReader(invalidData))
  
  _, err := tr.Next()
  if err != nil {
    fmt.Printf("Error reading tar: %v\n", err)
    return
  }
  
  fmt.Println("Archive read successfully")
}

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

go"Error reading tar: tar: invalid tar header"

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

  • функцию tar.NewReader,
    которая создает новый объект tar.Reader для чтения архива
  • метод tar.Reader.Next,
    который переходит к следующему файлу в TAR-архиве
  • тип tar.Header,
    который содержит метаданные файла в архиве
  • тип tar.Writer,
    который используется для создания TAR-архивов