cpp

Чтение из файла

Для чтения данных из файла предназначены следующие методы структуры File:

  • Read() — считывает из файла максимум len(b) байтов или оставшиеся байты и записывает их в байтовый слайс b. Формат метода:
(*os.File).Read(b []byte) (n int, err error)

Метод возвращает два значения. Через первое значение доступно число считанных байтов. Через второе значение доступен объект ошибки или nil, если операция выполнена успешно. В конце файла возвращается 0, io.EOF. Пример чтения всего содержимого файла:

func test() {
   file, err := os.Open(`C:\book\file.txt`)
   if err != nil {
      fmt.Println(err)
      return
   }
   defer file.Close()
   buf := make([]byte, 16)
   for {
      n, err := file.Read(buf)
      if err != nil {
         if err != io.EOF {
            fmt.Println(err)
            return
         }
         break
      }
      fmt.Print(string(buf[0:n]))
   }
}
  • ReadAt() — считывает из файла максимум len(b) байтов или оставшиеся байты и записывает их в байтовый слайс b. Считывание начинается с позиции off. Формат метода:
(*os.File).ReadAt(b []byte, off int64) (n int, err error)

Метод возвращает два значения. Через первое значение доступно число считанных байтов. Через второе значение доступен объект ошибки или nil. В конце файла возвращается io.EOF, причем в случае когда n < len(b). Пример:

func test() {
   file, err := os.Open(`C:\book\file.txt`)
   if err != nil {
      fmt.Println(err)
      return
   }
   defer file.Close()
   buf := make([]byte, 14)
   n, err := file.ReadAt(buf, 14)
   if err != nil && err != io.EOF {
      fmt.Println(err)
      return
   }
   fmt.Print(string(buf[0:n]))
}

Структура File реализует интерфейс io.Reader:

type Reader interface {
   Read(p []byte) (n int, err error)
}

Благодаря этому для чтения из файла мы можем использовать функции из пакета fmt:

  • Fscan() — функция принимает объект io.Reader и один или несколько параметров через запятую. В качестве значения нужно передать адрес переменной, в которую будет записано прочитанное значение. Чтобы передать адрес следует перед названием переменной добавить символ &. Функция возвращает два значения. Первое значение содержит количество успешных записей. Через второе значение можно получить сообщение об ошибке. Если ошибка не возникла, то значением будет nil. Формат функции:
fmt.Fscan(r io.Reader, a ...interface{}) (n int, err error)

Пример:

func test() {
   b := []byte("10 20")
   err := os.WriteFile(`C:\book\test.txt`, b, 0o777)
   if err != nil {
      fmt.Println(err)
      return
   }
   file, err := os.Open(`C:\book\test.txt`)
   if err != nil {
      fmt.Println(err)
      return
   }
   defer file.Close()
   x, y := 0, 0
   n, err := fmt.Fscan(file, &x, &y)
   fmt.Println(n, err) // 2 <nil>
   fmt.Println(x, y)   // 10 20
}
  • Fscanln() — функция принимает объект io.Reader и один или несколько параметров через запятую. В качестве значения нужно передать адрес переменной, в которую будет записано прочитанное значение. Чтобы передать адрес следует перед названием переменной добавить символ &. Функция возвращает два значения. Первое значение содержит количество успешных записей. Через второе значение можно получить сообщение об ошибке. Если ошибка не возникла, то значением будет nil. В отличие от функции Fscan() функция Fscanln() после последнего значения ожидает символ перевода строки или конец строки. Если это не так, то через второе возвращаемое значение будет доступно сообщение об ошибке. При этом количество успешных записей может быть не равно 0. Формат функции:
fmt.Fscanln(r io.Reader, a ...interface{}) (n int, err error)

Пример:

func test() {
   b := []byte("10 20")
   err := os.WriteFile(`C:\book\test.txt`, b, 0o777)
   if err != nil {
      fmt.Println(err)
      return
   }
   file, err := os.Open(`C:\book\test.txt`)
   if err != nil {
      fmt.Println(err)
      return
   }
   defer file.Close()
   x, y := 0, 0
   n, err := fmt.Fscanln(file, &x, &y)
   fmt.Println(n, err) // 2 <nil>
   fmt.Println(x, y)   // 10 20
}
  • Fscanf() — функция принимает объект io.Reader, строку формата и один или несколько параметров через запятую. В качестве значения нужно передать адрес переменной, в которую будет записано прочитанное значение. Чтобы передать адрес следует перед названием переменной добавить символ &. Внутри строки формата можно указать обычные символы и спецификаторы формата, начинающиеся с символа % (см. описание функции Printf() в разд. 1.9). Количество спецификаторов должно совпадать с количеством переданных параметров. Функция возвращает два значения. Первое значение содержит количество успешных записей. Через второе значение можно получить сообщение об ошибке. Если ошибка не возникла, то значением будет nil. Формат функции:
fmt.Fscanf(r io.Reader, format string,
           a ...interface{}) (n int, err error)

Пример:

func test() {
   b := []byte("10 20")
   err := os.WriteFile(`C:\book\test.txt`, b, 0o777)
   if err != nil {
      fmt.Println(err)
      return
   }
   file, err := os.Open(`C:\book\test.txt`)
   if err != nil {
      fmt.Println(err)
      return
   }
   defer file.Close()
   x, y := 0, 0
   n, err := fmt.Fscanf(file, "%d %d", &x, &y)
   fmt.Println(n, err) // 2 <nil>
   fmt.Println(x, y)   // 10 20
}

Функция ReadFile() из пакета os позволяет считать все содержимое файла в байтовый слайс. Формат функции:

os.ReadFile(name string) ([]byte, error)

В качестве параметра функция принимает абсолютный или относительный путь к файлу. Функция возвращает два значения. Через первое значение доступен байтовый слайс. Через второе значение можно получить сообщение об ошибке. Если ошибка не возникла, то значением будет nil. Пример:

func test() {
   b, err := os.ReadFile(`C:\book\file.txt`)
   if err != nil {
      fmt.Println(err)
      return
   }
   fmt.Println(string(b))
}

Считать все содержимое файла в байтовый буфер можно так:

func test() {
   file, err := os.Open(`C:\book\file.txt`)
   if err != nil {
      fmt.Println(err)
      return
   }
   defer file.Close()
   var buf bytes.Buffer
   if _, err = buf.ReadFrom(file); err != nil {
      fmt.Println(err)
      return
   }
   fmt.Println(buf.String())
}

В качестве примера запишем структуру в файл, а затем считаем структуру из файла и выведем значения (листинг 14.1).

Листинг 14.1. Сохранение структуры в файл

package main

import (
   "encoding/json"
   "fmt"
   "os"
)

type Point struct {
   X int `json:"x"`
   Y int `json:"y"`
}

func main() {
   name := `C:\book\test.txt`
   obj1 := Point{10, 20}
   err := Write(name, obj1)
   if err != nil {
      fmt.Println(err)
      return
   }
   obj2, err := Read(name)
   if err != nil {
      fmt.Println(err)
      return
   }
   fmt.Println(obj2)
}
func Write(name string, obj Point) error {
   b, err := json.Marshal(obj)
   if err != nil {
      return err
   }
   err = os.WriteFile(name, b, 0o777)
   if err != nil {
      return err
   }
   return nil
}
func Read(name string) (Point, error) {
   b, err := os.ReadFile(name)
   if err != nil {
      return Point{}, err
   }
   obj := Point{}
   err = json.Unmarshal(b, &obj)
   if err != nil {
      return Point{}, err
   }
   return obj, nil
}

Для чтения данных из файла можно воспользоваться следующими функциями из пакета io:

  • ReadAll() — считывает все содержимое файла в байтовый слайс. Формат функции:
io.ReadAll(r io.Reader) ([]byte, error)

В качестве параметра функция принимает объект io.Reader. Функция возвращает два значения. Через первое значение доступен байтовый слайс. Через второе значение можно получить сообщение об ошибке. Если ошибка не возникла, то значением будет nil. Пример:

func test() {
   file, err := os.Open(`C:\book\file.txt`)
   if err != nil {
      fmt.Println(err)
      return
   }
   defer file.Close()
   b, err := io.ReadAll(file)
   if err != nil {
      fmt.Println(err)
      return
   }
   fmt.Println(string(b))
}
  • ReadFull() — считывает из файла ровно len(buf) байтов и записывает их в байтовый слайс buf. Формат метода:
io.ReadFull(r io.Reader, buf []byte) (n int, err error)

Метод возвращает два значения. Через первое значение доступно число считанных байтов. Через второе значение доступен объект ошибки или nil, если операция выполнена успешно. Если в конце файла считано меньше len(buf) байтов, то возвращается ошибка io.ErrUnexpectedEOF. В конце файла возвращается io.EOF. Пример чтения всего содержимого файла:

func test() {
   file, err := os.Open(`C:\book\file.txt`)
   if err != nil {
      fmt.Println(err)
      return
   }
   defer file.Close()
   buf := make([]byte, 16)
   for {
      n, err := io.ReadFull(file, buf)
      if err != nil {
         if err != io.EOF && err != io.ErrUnexpectedEOF {
            fmt.Println(err)
            return
         }
         if err == io.ErrUnexpectedEOF {
            // Прочитано меньше len(buf)
         } else {
            break
         }
      }
      fmt.Print(string(buf[0:n]))
   }
}
  • Copy() — считывает все данные из потока src и записывает их в поток dst. Формат метода:
io.Copy(dst io.Writer, src io.Reader) (written int64, err error)

Метод возвращает два значения. Через первое значение доступно число скопированных байтов. Через второе значение доступен объект ошибки или nil, если операция выполнена успешно. Пример чтения всего содержимого файла и вывода его в стандартный поток os.Stdout:

func test() {
   file, err := os.Open(`C:\book\file.txt`)
   if err != nil {
      fmt.Println(err)
      return
   }
   defer file.Close()
   n, err := io.Copy(os.Stdout, file)
   if err != nil {
      fmt.Println(err)
      return
   }
   fmt.Println(n)
}
  • CopyBuffer() — считывает все данные из потока src и записывает их в поток dst. При этом используется буфер, указанный в третьем параметре. Формат метода:
io.CopyBuffer(dst io.Writer, src io.Reader,
              buf []byte) (written int64, err error)

Метод возвращает два значения. Через первое значение доступно число скопированных байтов. Через второе значение доступен объект ошибки или nil, если операция выполнена успешно. Пример чтения всего содержимого файла и вывода его в стандартный поток os.Stdout:

func test() {
   file, err := os.Open(`C:\book\file.txt`)
   if err != nil {
      fmt.Println(err)
      return
   }
   defer file.Close()
   buf := make([]byte, 16)
   n, err := io.CopyBuffer(os.Stdout, file, buf)
   if err != nil {
      fmt.Println(err)
      return
   }
   fmt.Println(n)
}
  • CopyN() — считывает n байтов из потока src и записывает их в поток dst. Формат метода:
io.CopyN(dst io.Writer, src io.Reader,
         n int64) (written int64, err error)

Метод возвращает два значения. Через первое значение доступно число скопированных байтов. Через второе значение доступен объект ошибки или nil, если операция выполнена успешно. Пример:

func test() {
   file, err := os.Open(`C:\book\file.txt`)
   if err != nil {
      fmt.Println(err)
      return
   }
   defer file.Close()
   n, err := io.CopyN(os.Stdout, file, 14)
   if err != nil {
      fmt.Println(err)
      return
   }
   fmt.Println(n)
}

Учебник Go (Golang)
Учебник Go (Golang) в формате PDF

Помощь сайту

ЮMoney (Yandex-деньги): 410011140483022

ПАО Сбербанк:
Счет: 40817810855006152256
Реквизиты банка:
Наименование: СЕВЕРО-ЗАПАДНЫЙ БАНК ПАО СБЕРБАНК
Корреспондентский счет: 30101810500000000653
БИК: 044030653
КПП: 784243001
ОКПО: 09171401
ОКОНХ: 96130
Скриншот реквизитов

cpp