Складемо список сумісних з Go 1 всіх способів читання та запису файлів у Go.
Оскільки API файлів нещодавно змінився, а більшість інших відповідей не працює з Go 1. Вони також пропускають, bufio
що важливо IMHO.
У наступних прикладах я копіюю файл, читаючи з нього та записуючи у файл призначення.
Почніть з основ
package main
import (
"io"
"os"
)
func main() {
// open input file
fi, err := os.Open("input.txt")
if err != nil {
panic(err)
}
// close fi on exit and check for its returned error
defer func() {
if err := fi.Close(); err != nil {
panic(err)
}
}()
// open output file
fo, err := os.Create("output.txt")
if err != nil {
panic(err)
}
// close fo on exit and check for its returned error
defer func() {
if err := fo.Close(); err != nil {
panic(err)
}
}()
// make a buffer to keep chunks that are read
buf := make([]byte, 1024)
for {
// read a chunk
n, err := fi.Read(buf)
if err != nil && err != io.EOF {
panic(err)
}
if n == 0 {
break
}
// write a chunk
if _, err := fo.Write(buf[:n]); err != nil {
panic(err)
}
}
}
Тут я використав os.Open
і os.Create
які зручні обгортки навколо os.OpenFile
. Нам зазвичай не потрібно телефонувати OpenFile
безпосередньо.
Помітьте обробку EOF. Read
намагається виконати buf
кожен виклик і повертається io.EOF
як помилка, якщо при цьому доходить до кінця файлу. У цьому випадку buf
все одно зберігатимуться дані. Подальші дзвінки Read
повертають нуль як кількість прочитаних байтів і те саме, що io.EOF
і помилка. Будь-яка інша помилка призведе до паніки.
Використання bufio
package main
import (
"bufio"
"io"
"os"
)
func main() {
// open input file
fi, err := os.Open("input.txt")
if err != nil {
panic(err)
}
// close fi on exit and check for its returned error
defer func() {
if err := fi.Close(); err != nil {
panic(err)
}
}()
// make a read buffer
r := bufio.NewReader(fi)
// open output file
fo, err := os.Create("output.txt")
if err != nil {
panic(err)
}
// close fo on exit and check for its returned error
defer func() {
if err := fo.Close(); err != nil {
panic(err)
}
}()
// make a write buffer
w := bufio.NewWriter(fo)
// make a buffer to keep chunks that are read
buf := make([]byte, 1024)
for {
// read a chunk
n, err := r.Read(buf)
if err != nil && err != io.EOF {
panic(err)
}
if n == 0 {
break
}
// write a chunk
if _, err := w.Write(buf[:n]); err != nil {
panic(err)
}
}
if err = w.Flush(); err != nil {
panic(err)
}
}
bufio
тут просто виступає буфером, тому що ми не маємо великого відношення до даних. У більшості інших ситуацій (особливо з текстовими файлами) bufio
дуже корисно, надаючи нам приємний API для читання та запису легко та гнучко, в той час як він обробляє буферизацію за кадром.
Використання ioutil
package main
import (
"io/ioutil"
)
func main() {
// read the whole file at once
b, err := ioutil.ReadFile("input.txt")
if err != nil {
panic(err)
}
// write the whole body at once
err = ioutil.WriteFile("output.txt", b, 0644)
if err != nil {
panic(err)
}
}
Легкий як пиріг! Але використовуйте його лише в тому випадку, якщо ви впевнені, що не маєте справу з великими файлами.