Hãy tạo một danh sách tương thích với Go 1 về tất cả các cách để đọc và ghi tệp trong Go.
Bởi vì API tệp đã thay đổi gần đây và hầu hết các câu trả lời khác không hoạt động với Go 1. Họ cũng bỏ lỡ bufio
IMHO quan trọng.
Trong các ví dụ sau tôi sao chép một tệp bằng cách đọc từ nó và ghi vào tệp đích.
Bắt đầu với những điều cơ bản
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)
}
}
}
Ở đây tôi đã sử dụng os.Open
và os.Create
đó là các trình bao bọc thuận tiện xung quanh os.OpenFile
. Chúng tôi thường không cần gọi OpenFile
trực tiếp.
Thông báo điều trị EOF. Read
cố gắng điền buf
vào mỗi cuộc gọi và trả về io.EOF
là lỗi nếu nó đến cuối tập tin khi thực hiện. Trong trường hợp buf
này vẫn sẽ giữ dữ liệu. Các cuộc gọi tiếp theo Read
trả về 0 là số byte được đọc và giống io.EOF
như lỗi. Bất kỳ lỗi nào khác sẽ dẫn đến hoảng loạn.
Sử dụng 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
chỉ đóng vai trò là bộ đệm ở đây, vì chúng ta không liên quan nhiều đến dữ liệu. Trong hầu hết các tình huống khác (đặc biệt với các tệp văn bản) bufio
rất hữu ích bằng cách cung cấp cho chúng tôi một API đẹp để đọc và viết dễ dàng và linh hoạt, trong khi nó xử lý bộ đệm phía sau hậu trường.
Sử dụng 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)
}
}
Dễ như ăn bánh! Nhưng chỉ sử dụng nó nếu bạn chắc chắn rằng bạn không xử lý các tệp lớn.