Тип io.SectionReader

Тип io.SectionReader используется для создания объекта чтения, который представляет собой срез (фрагмент) данных из другого источника данных, реализующего интерфейс io.ReaderAt. В первый параметр мы передаем объект, поддерживающий чтение по смещению (например, файл или массив байт), во второй - начальное смещение (offset) от начала данных, а в третий - количество байт, которые будут доступны для чтения.

Синтаксис

goio.NewSectionReader(readerAt, offset, length)

Пример

Давайте создадим участок чтения из строки байт (слайса байт), начиная со смещения 5 и длиной 10 байт:

gopackage main

import (
  "fmt"
  "io"
  "strings"
)

func main() {
  // Создаем источник данных в виде строки
  data := "01234567890123456789"
  reader := strings.NewReader(data)

  // Создаем SectionReader для чтения байтов с 5-го по 14-й
  sectionReader := io.NewSectionReader(reader, 5, 10)

  // Читаем фрагмент в срез байт
  buf := make([]byte, 10)
  n, err := sectionReader.Read(buf)
  if err != nil && err != io.EOF {
    fmt.Printf("error: %v", err)
    return
  }

  fmt.Printf("%s", string(buf[:n]))
}

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

go"5678901234"

Пример

Продемонстрируем использование метода Seek для изменения текущей позиции чтения внутри SectionReader:

gopackage main

import (
  "fmt"
  "io"
  "strings"
)

func main() {
  // Исходные данные
  data := "0123456789abcdef"
  reader := strings.NewReader(data)

  // Создаем SectionReader для фрагмента с 0 по 16 байт
  sectionReader := io.NewSectionReader(reader, 0, 16)

  // Перемещаем указатель на 5 байт от начала
  sectionReader.Seek(5, io.SeekStart)

  // Читаем 5 байт
  buf := make([]byte, 5)
  n, err := sectionReader.Read(buf)
  if err != nil && err != io.EOF {
    fmt.Printf("error: %v", err)
    return
  }

  fmt.Printf("%s", string(buf[:n]))
}

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

go"56789"

Пример

Покажем, как работает метод Size, возвращающий размер фрагмента, а также чтение с конца фрагмента с использованием отрицательного смещения:

gopackage main

import (
  "fmt"
  "io"
  "strings"
)

func main() {
  // Исходные данные длиной 20 байт
  data := "0123456789abcdefghij"
  reader := strings.NewReader(data)

  // Создаем SectionReader для фрагмента с 5 по 20 байт
  sectionReader := io.NewSectionReader(reader, 5, 15)

  // Получаем размер фрагмента
  size := sectionReader.Size()
  fmt.Printf("size: %d\n", size)

  // Перемещаем указатель на 10 байт назад от конца
  sectionReader.Seek(-10, io.SeekEnd)

  // Читаем 5 байт
  buf := make([]byte, 5)
  n, err := sectionReader.Read(buf)
  if err != nil && err != io.EOF {
    fmt.Printf("error: %v", err)
    return
  }

  fmt.Printf("tail: %s", string(buf[:n]))
}

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

go"size: 15"
"tail: 45678"

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

  • тип io.ReaderAt,
    который является основой для создания SectionReader
  • функцию io.LimitReader,
    которая ограничивает количество байт для чтения
  • метод os.File.Seek,
    который позволяет устанавливать позицию в файле
  • функцию io.ReadFull,
    которая гарантированно читает указанное количество байт