Go读写文件

摘要

Go读写文件的一些包的使用方法

io/ioutil

主要是操作文件、文件夹

ReadAll

1
func ReadAll(r io.Reader) ([]byte, error)
  • 读取r中的所有数据,返回读取的数据和遇到的错误
  • 如果读取成功,则err返回nil,而不是EOF,因为ReadAll定义为读取所有数据,所以不会把EOF当做错误处理。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package main

import (
"crypto/tls"
"fmt"
"io/ioutil"
"net/http"
)

func main() {

link := "http://xkcd.com/55"

tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
client := &http.Client{Transport: tr}
response, err := client.Get(link)
if err != nil {
fmt.Println(err)
}
defer response.Body.Close()

//block forever at the next line
content, _ := ioutil.ReadAll(response.Body)

fmt.Println(string(content))

}

ReadDir

1
func ReadDir(dirname string) ([]os.FileInfo, error)
  • ReadDir读取指定目录中的所有目录和文件(不包括子目录)
  • 返回读取到的文件信息列表和遇到的错误,列表是经过排序的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package main

import (
"fmt"
"io/ioutil"
"log"
)

func main() {

files, err := ioutil.ReadDir(".")
if err != nil {
log.Fatal(err)
}

for _, file := range files {
fmt.Println(file.Name())
}

}

ReadFile

1
func ReadFile(filename string) ([]byte, error)
  • ReadFile读取文件中的所有数据,返回读取的数据和遇到的错误
  • 如果读取成功,则err返回nil,而不是EOF
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package main

import (
"bufio"
"fmt"
"io"
"io/ioutil"
"os"
)

// Reading files requires checking most calls for errors.
// This helper will streamline our error checks below.
func check(e error) {
if e != nil {
panic(e)
}
}

func main() {

// Perhaps the most basic file reading task is
// slurping a file's entire contents into memory.
dat, err := ioutil.ReadFile("test.txt")
check(err)
fmt.Print(string(dat))

// You'll often want more control over how and what
// parts of a file are read. For these tasks, start
// by `Open`ing a file to obtain an `os.File` value.
f, err := os.Open("test.txt")
check(err)

// Read some bytes from the beginning of the file.
// Allow up to 5 to be read but also note how many
// actually were read.
b1 := make([]byte, 5)
n1, err := f.Read(b1)
check(err)
fmt.Printf("%d bytes: %s\n", n1, string(b1))

// You can also `Seek` to a known location in the file
// and `Read` from there.
o2, err := f.Seek(6, 0)
check(err)
b2 := make([]byte, 2)
n2, err := f.Read(b2)
check(err)
fmt.Printf("%d bytes @ %d: %s\n", n2, o2, string(b2))

// The `io` package provides some functions that may
// be helpful for file reading. For example, reads
// like the ones above can be more robustly
// implemented with `ReadAtLeast`.
o3, err := f.Seek(6, 0)
check(err)
b3 := make([]byte, 2)
n3, err := io.ReadAtLeast(f, b3, 2)
check(err)
fmt.Printf("%d bytes @ %d: %s\n", n3, o3, string(b3))

// There is no built-in rewind, but `Seek(0, 0)`
// accomplishes this.
_, err = f.Seek(0, 0)
check(err)

// The `bufio` package implements a buffered
// reader that may be useful both for its efficiency
// with many small reads and because of the additional
// reading methods it provides.
r4 := bufio.NewReader(f)
b4, err := r4.Peek(5)
check(err)
fmt.Printf("5 bytes: %s\n", string(b4))

// Close the file when you're done (usually this would
// be scheduled immediately after `Open`ing with
// `defer`).
f.Close()

}

TempDir

1
func TempDir(dir, prefix string) (name string, err error)
  • 操作系统中一般都会提供临时目录
  • 比如linux下的/tmp目录(通过os.TempDir()可以获取到)
  • 有时候,我们自己需要创建临时目录,比如Go工具链源码中(src/cmd/go/build.go
  • 通过TempDir创建一个临时目录,用于存放编译过程的临时文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package main

import (
"io/ioutil"
"log"
"os"
"path/filepath"
)

func main() {
content := []byte("temporary file's content")
dir, err := ioutil.TempDir("", "example")
if err != nil {
log.Fatal(err)
}

defer os.RemoveAll(dir) // clean up

tmpfn := filepath.Join(dir, "tmpfile")
if err := ioutil.WriteFile(tmpfn, content, 0666); err != nil {
log.Fatal(err)
}
}

TempFile

1
func TempFile(dir, prefix string) (f *os.File, err error)
  • TempFiledir目录中创建一个以prefix为前缀的临时文件,并将其以读写模式打开。返回创建的文件对象和遇到的错误
  • 如果dir为空,则在默认的临时目录中创建文件(参见os.TempDir
  • 多次调用会创建不同的临时文件,调用者可以通过f.Name()获取文件的完整路径
  • 调用本函数所创建的临时文件,应该由调用者自己删除。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package main

import (
"io/ioutil"
"log"
"os"
)

func main() {
content := []byte("temporary file's content")
tmpfile, err := ioutil.TempFile("", "example")
if err != nil {
log.Fatal(err)
}

defer os.Remove(tmpfile.Name()) // clean up

if _, err := tmpfile.Write(content); err != nil {
log.Fatal(err)
}
if err := tmpfile.Close(); err != nil {
log.Fatal(err)
}
}

WriteFile

1
func WriteFile(filename string, data []byte, perm os.FileMode) error
  • WriteFile向文件中写入数据,写入前会清空文件
  • 如果文件不存在,则会以指定的权限创建该文件
  • 返回遇到的错误
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package main

import (
"bufio"
"fmt"
"io/ioutil"
"os"
)

func check(e error) {
if e != nil {
panic(e)
}
}

func main() {

// To start, here's how to dump a string (or just
// bytes) into a file.
d1 := []byte("hello\ngo\n")
err := ioutil.WriteFile("/tmp/dat1", d1, 0644)
check(err)

// For more granular writes, open a file for writing.
f, err := os.Create("/tmp/dat2")
check(err)

// It's idiomatic to defer a `Close` immediately
// after opening a file.
defer f.Close()

// You can `Write` byte slices as you'd expect.
d2 := []byte{115, 111, 109, 101, 10}
n2, err := f.Write(d2)
check(err)
fmt.Printf("wrote %d bytes\n", n2)

// A `WriteString` is also available.
n3, err := f.WriteString("writes\n")
fmt.Printf("wrote %d bytes\n", n3)

// Issue a `Sync` to flush writes to stable storage.
f.Sync()

// `bufio` provides buffered writers in addition
// to the buffered readers we saw earlier.
w := bufio.NewWriter(f)
n4, err := w.WriteString("buffered\n")
fmt.Printf("wrote %d bytes\n", n4)

// Use `Flush` to ensure all buffered operations have
// been applied to the underlying writer.
w.Flush()

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package main

import (
"fmt"
"io/ioutil"
)

func main() {
b, err := ioutil.ReadFile("test.log")
if err != nil {
fmt.Print(err)
}
fmt.Println(b)
str := string(b)
fmt.Println(str)
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main

import (
"io/ioutil"
)

func check(e error) {
if e != nil {
panic(e)
}
}

func main() {

d1 := []byte("hello\ngo\n")
err := ioutil.WriteFile("test.txt", d1, 0644)
check(err)
}

os

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
package main

import (
"log"
"os"
)

func main() {
//需要提供文件路径、打开模式、文件权限
f, err := os.OpenFile("notes.txt", os.O_RDWR|os.O_CREATE, 0755)
if err != nil {
log.Fatal(err)
}
if err := f.Close(); err != nil {
log.Fatal(err)
}
}

///////读方法

package main

import (
"bufio"
"fmt"
"io"
"io/ioutil"
"os"
)

func check(e error) {
if e != nil {
panic(e)
}
}

func main() {

f, err := os.Open("/tmp/dat")
check(err)

b1 := make([]byte, 5)
n1, err := f.Read(b1)
check(err)
fmt.Printf("%d bytes: %s\n", n1, string(b1))

o2, err := f.Seek(6, 0)
check(err)
b2 := make([]byte, 2)
n2, err := f.Read(b2)
check(err)
fmt.Printf("%d bytes @ %d: %s\n", n2, o2, string(b2))

o3, err := f.Seek(6, 0)
check(err)
b3 := make([]byte, 2)
n3, err := io.ReadAtLeast(f, b3, 2)
check(err)
fmt.Printf("%d bytes @ %d: %s\n", n3, o3, string(b3))

_, err = f.Seek(0, 0)
check(err)

r4 := bufio.NewReader(f)
b4, err := r4.Peek(5)
check(err)
fmt.Printf("5 bytes: %s\n", string(b4))

f.Close()

}

写方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package main

import (
"bufio"
"fmt"
"io/ioutil"
"os"
)

func check(e error) {
if e != nil {
panic(e)
}
}

func main() {

f, err := os.Create("/tmp/dat2")
check(err)

defer f.Close()

d2 := []byte{115, 111, 109, 101, 10}
n2, err := f.Write(d2)
check(err)
fmt.Printf("wrote %d bytes\n", n2)

n3, err := f.WriteString("writes\n")
fmt.Printf("wrote %d bytes\n", n3)


f.Sync()


w := bufio.NewWriter(f)
n4, err := w.WriteString("buffered\n")
fmt.Printf("wrote %d bytes\n", n4)

w.Flush()

}

几种读取文件方法速度比较

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
package main

import (
"bufio"
"fmt"
"io"
"io/ioutil"
"os"
"time"
)

func read0(path string) string {
f, err := ioutil.ReadFile(path)
if err != nil {
fmt.Printf("%s\n", err)
panic(err)
}
return string(f)
}

func read1(path string) string {
fi, err := os.Open(path)
if err != nil {
panic(err)
}
defer fi.Close()

chunks := make([]byte, 1024, 1024)
buf := make([]byte, 1024)
for {
n, err := fi.Read(buf)
if err != nil && err != io.EOF {
panic(err)
}
if 0 == n {
break
}
chunks = append(chunks, buf[:n]...)
}
return string(chunks)
}

func read2(path string) string {
fi, err := os.Open(path)
if err != nil {
panic(err)
}
defer fi.Close()
r := bufio.NewReader(fi)

chunks := make([]byte, 1024, 1024)

buf := make([]byte, 1024)
for {
n, err := r.Read(buf)
if err != nil && err != io.EOF {
panic(err)
}
if 0 == n {
break
}
chunks = append(chunks, buf[:n]...)
}
return string(chunks)
}

func read3(path string) string {
fi, err := os.Open(path)
if err != nil {
panic(err)
}
defer fi.Close()
fd, err := ioutil.ReadAll(fi)
return string(fd)
}

func main() {

file := "test.log"

start := time.Now()

read0(file)
t0 := time.Now()
fmt.Printf("Cost time %v\n", t0.Sub(start))

read1(file)
t1 := time.Now()
fmt.Printf("Cost time %v\n", t1.Sub(t0))

read2(file)
t2 := time.Now()
fmt.Printf("Cost time %v\n", t2.Sub(t1))

read3(file)
t3 := time.Now()
fmt.Printf("Cost time %v\n", t3.Sub(t2))

}