cpp

Чтение и запись файлов

Очень часто нужно сохранить какие-либо данные. Для этого существуют два способа: сохранение в файл и сохранение в базу данных. Первый способ используется при сохранении информации небольшого объема. Если объем велик, то лучше (и удобнее) воспользоваться базой данных.

Открытие и закрытие файла

Прежде чем работать с файлом, необходимо создать объект файла с помощью следующих функций из пакета os:

  • Open() — открывает существующий файл только для чтения. Формат функции:
os.Open(name string) (*os.File, error)

В качестве параметра указывается относительный или абсолютный путь к файлу. Функция возвращает два значения. Через первое значение в случае успеха доступен указатель на объект структуры File, с помощью которого можно работать с файлом. Если произошла ошибка, например, файл не существует, то объект ошибки (тип *fs.PathError) доступен через второе значение. Если ошибка не возникла, то второе значение будет равно nil.

Прочитаем все содержимое файла C:\book\test.txt в байтовый буфер (первоначально создайте файл в кодировке UTF-8, если не создавали его при чтении разд. 5.5.2):

// import "os"
// import "bytes"
func test() {
   file, err := os.Open(`C:\book\test.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())
}

Если файл не существует, то получим следующее сообщение об ошибке:

open C:\book\test.txt: The system cannot find the file specified.
  • OpenFile() — открывает файл. Формат функции:
os.OpenFile(name string, flag int,
            perm fs.FileMode) (*os.File, error)
type FileMode uint32

В качестве первого параметра указывается относительный или абсолютный путь к файлу. В параметре flag могут быть указаны следующие константы, задающие режим открытия файла (или их комбинация через символ |):

  • os.O_RDONLY — только чтение;
  • os.O_WRONLY — только запись;
  • os.O_RDWR — чтение и запись;
  • os.O_APPEND — добавление в конец файла;
  • os.O_CREATE — создать файл, если он не существует;
  • os.O_TRUNC — очистить содержимое файла;
  • os.O_CREATE | os.O_EXCL — создать файл. Если файл уже существует, то вернуть код ошибки;
  • os.O_SYNC — синхронный режим.

В параметре perm указывается режим доступа к создаваемому файлу.

Функция возвращает два значения. Через первое значение в случае успеха доступен указатель на объект структуры File, с помощью которого можно работать с файлом. Если произошла ошибка, например, файл не существует, то объект ошибки (тип *fs.PathError) доступен через второе значение. Если ошибка не возникла, то второе значение будет равно nil.

Рассмотрим несколько примеров. Откроем файл на запись и запишем в него одну строку. Если файл не существует, то создадим его. Если файл существует, то очистим его:

func test() {
   mode := os.O_WRONLY | os.O_CREATE | os.O_TRUNC
   file, err := os.OpenFile(`C:\book\file.txt`, mode, 0o777)
   if err != nil {
      fmt.Println(err)
      return
   }
   defer file.Close()
   if _, err = file.WriteString("Строка1\n"); err != nil {
      fmt.Println(err)
      return
   }
   fmt.Println("Операция выполнена успешно")
}

Добавим еще одну строку в конец файла:

func test() {
   mode := os.O_WRONLY | os.O_CREATE | os.O_APPEND
   file, err := os.OpenFile(`C:\book\file.txt`, mode, 0o777)
   if err != nil {
      fmt.Println(err)
      return
   }
   defer file.Close()
   if _, err = file.WriteString("Строка2\n"); err != nil {
      fmt.Println(err)
      return
   }
   fmt.Println("Операция выполнена успешно")
}

Прочитаем содержимое файла в байтовый буфер:

func test() {
   mode :=  os.O_RDONLY
   file, err := os.OpenFile(`C:\book\file.txt`, mode, 0o777)
   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())
}
  • Create() — открывает файл в режиме чтения и записи. Если файл не существует, то он будет создан с правами доступа 0o666. Если файл существует, то он будет очищен. Формат функции:
os.Create(name string) (*os.File, error)

В качестве параметра указывается относительный или абсолютный путь к файлу. Функция возвращает два значения. Через первое значение в случае успеха доступен указатель на объект структуры File, с помощью которого можно работать с файлом. Если произошла ошибка, то объект ошибки (тип *fs.PathError) доступен через второе значение. Если ошибка не возникла, то второе значение будет равно nil.

Запишем строку в файл:

func test() {
   file, err := os.Create(`C:\book\file.txt`)
   if err != nil {
      fmt.Println(err)
      return
   }
   defer file.Close()
   if _, err = file.WriteString("Строка"); err != nil {
      fmt.Println(err)
      return
   }
   fmt.Println("Операция выполнена успешно")
}
  • NewFile() — открывает файл по файловому дескриптору fd. Функция возвращает указатель на объект структуры File. Если файловый дескриптор не является допустимым, то возвращается значение nil. Формат функции:
os.NewFile(fd uintptr, name string) *os.File

Пример:

func test() {
   file, err := os.Create(`C:\book\file.txt`)
   if err != nil {
      fmt.Println(err)
      return
   }
   defer file.Close()
   file2 := os.NewFile(file.Fd(), `file2.txt`)
   if file2 == nil {
      fmt.Println("nil")
      return
   }
   fmt.Println(file.Name())  // C:\book\file.txt
   fmt.Println(file2.Name()) // file2.txt
   if _, err = file2.WriteString("Строка"); err != nil {
      fmt.Println(err)
      return
   }
   fmt.Println("Операция выполнена успешно")
}

После открытия файла доступны следующие основные методы:

  • Close() — закрывает файл. Формат метода:
(*os.File).Close() error

Чтобы файл был обязательно закрыт, даже при генерации паники, следует использовать инструкцию defer:

defer file.Close()
  • Name() — возвращает название файла. Формат метода:
(*os.File).Name() string

Пример:

fmt.Println(file.Name()) // C:\book\file.txt
  • Fd() — возвращает дескриптор файла. Формат метода:
(*os.File).Fd() uintptr

Пример:

fmt.Println(file.Fd())   // 196

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

Реквизиты

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

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

cpp