Интерфейс io.ReaderAt
Интерфейс io.ReaderAt определяет метод ReadAt,
который позволяет читать данные из файла, начиная с указанного смещения.
В отличие от стандартного io.Reader, который читает последовательно,
ReaderAt позволяет выполнять произвольный доступ к данным.
Метод принимает срез байтов для записи данных и смещение в байтах,
с которого начинается чтение.
Синтаксис
type ReaderAt interface {
ReadAt(p []byte, off int64) (n int, err error)
}
Метод ReadAt читает данные в срез p,
начиная с позиции off в источнике.
Возвращает количество прочитанных байтов и ошибку.
Пример
Откроем файл и прочитаем несколько байт с определенной позиции:
package main
import (
"fmt"
"io"
"os"
)
func main() {
file, err := os.Open("example.txt")
if err != nil {
fmt.Println("Error opening file:", err)
return
}
defer file.Close()
buf := make([]byte, 5)
n, err := file.ReadAt(buf, 10)
if err != nil && err != io.EOF {
fmt.Println("Error reading:", err)
return
}
fmt.Printf("Read %d bytes: %s\n", n, string(buf[:n]))
}
Результат выполнения кода:
"Read 5 bytes: world"
Пример
Используем io.NewSectionReader для чтения участка файла:
package main
import (
"fmt"
"io"
"os"
)
func main() {
file, err := os.Open("example.txt")
if err != nil {
fmt.Println("Error opening file:", err)
return
}
defer file.Close()
sectionReader := io.NewSectionReader(file, 5, 10)
buf := make([]byte, 6)
n, err := sectionReader.ReadAt(buf, 2)
if err != nil && err != io.EOF {
fmt.Println("Error reading:", err)
return
}
fmt.Printf("Read %d bytes: %s\n", n, string(buf[:n]))
}
Результат выполнения кода:
"Read 6 bytes: 345678"
Пример
Чтение с произвольной позиции в нескольких горутинах:
package main
import (
"fmt"
"io"
"os"
"sync"
)
func main() {
file, err := os.Open("largefile.dat")
if err != nil {
fmt.Println("Error opening file:", err)
return
}
defer file.Close()
var wg sync.WaitGroup
positions := []int64{0, 100, 200}
for _, pos := range positions {
wg.Add(1)
go func(offset int64) {
defer wg.Done()
buf := make([]byte, 10)
n, err := file.ReadAt(buf, offset)
if err != nil && err != io.EOF {
fmt.Printf("Error at offset %d: %v\n", offset, err)
return
}
fmt.Printf("Offset %d: %s\n", offset, string(buf[:n]))
}(pos)
}
wg.Wait()
}
Результат выполнения кода:
"Offset 0: 0123456789"
"Offset 100: abcdefghij"
"Offset 200: ABCDEFGHIJ"
Смотрите также
-
интерфейс
io.Reader,
который используется для последовательного чтения данных -
интерфейс
io.WriterAt,
который позволяет записывать данные с произвольной позиции -
функцию
os.File.ReadAt,
которая реализует интерфейс для файлового дескриптора -
тип
io.SectionReader,
который предоставляет доступ только к определенному участку данных