Eli's Blog

1. 读文件

  • os.Open(name string) (file *File, err error)

  • ioutil.ReadFile(name string) ([]byte, error) 适合小文件一次性读取

1.1 带缓存读取文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
func main() {
file, err := os.Open("./abc.txt")
if err != nil {
fmt.Printf("Open file error: %v\n", err)
return
}
defer file.Close()

reader := bufio.NewReader(file)
for {
// 按行读取
line, err := reader.ReadString('\n')
if err == io.EOF {
break
}
fmt.Print(line)
}
}

1.2 一次性读取文件:(小文件适用)

1
2
3
4
5
6
7
8
9
func main() {
bs, err := ioutil.ReadFile("./abc.txt")
if err != nil {
fmt.Printf("Read file error: %v\n", err)
return
}

fmt.Printf("%s\n", bs)
}

2. 写文件

1
os.OpenFile(name string, flag int, perm FileMode) (file *File, err error)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
func main() {
file, err := os.OpenFile("./xyz.txt", os.O_CREATE|os.O_WRONLY, 0600)
if err != nil {
fmt.Errorf("Open file error: %v\n", err)
return
}
defer file.Close()

msg := "Hello World!\n"

writer := bufio.NewWriter(file)
for i := 0; i < 5; i++ {
writer.Write([]byte(msg))
}
writer.Flush()
}

文件操作模式:

  • 覆盖写:os.O_WRONLY | os.O_TRUNC
  • 追加写:os.O_WRONLY | os.O_APPEND
  • 读写并追加:os.O_RDWR | os.OS_APPEND

3. 文件拷贝

3.1 直接拷贝文件内容 (小文件,文本文件)

1
2
3
4
5
6
7
8
9
10
11
12
func main() {
bs, err := ioutil.ReadFile("./abc.txt")
if err != nil {
fmt.Errorf("Read file error: %v\n", err)
return
}

err = ioutil.WriteFile("./xyz.txt", bs, 0600)
if err != nil {
fmt.Errorf("Write file error: %v", err)
}
}

3.2 带缓冲拷贝 (大文件,二进制文件)

io.Copy(dst Writer, src Reader) (written int64, err error)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
func CopyFile(dstFileName, srcFileName string) (written int64, err error) {
srcFile, err := os.OpenFile(srcFileName, os.O_RDONLY, 0)
if err != nil {
return 0, err
}
defer srcFile.Close()

dstFile, err := os.OpenFile(dstFileName, os.O_CREATE|os.O_WRONLY, 0600)
if err != nil {
return 0, err
}
defer dstFile.Close()

writer := bufio.NewWriter(dstFile)
reader := bufio.NewReader(srcFile)

written, err = io.Copy(writer, reader)
writer.Flush() // 需要自己去Flush

return
}

4. 文件是否存在

1
2
3
4
5
6
7
8
9
10
11
12
13
func IsFileExist(name string) (bool, error) {
_, err := os.Stat(name)
if err == nil {
return true, nil
}

if os.IsNotExist(err) {
fmt.Println("文件不存在")
return false, nil
}

return false, err
}

5. 字符统计

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
type Statistic struct {
Char int
Number int
Space int
Other int
}

func main() {
file, err := os.Open("./abc.txt")
if err != nil {
fmt.Printf("Open file error: %v\n", err)
return
}
defer file.Close()

stat := Statistic{}

reader := bufio.NewReader(file)
for {
bs, err := reader.ReadString('\n')
if err == io.EOF {
break
}

for _, c := range []rune(bs) {
switch {
case c >= 'a' && c <= 'z':
fallthrough
case c >= 'A' && c <= 'Z':
stat.Char++
case c >= '0' && c <= '9':
stat.Number++
case c == ' ' || c == '\t':
stat.Space++
default:
stat.Other++
}
}
}

fmt.Printf("%v\n", stat)
}

6. 目录遍历

  • type WalkFunc func(path string, info os.FileInfo, err error) error
  • func Walk(root string, walkFn WalkFunc) error
1
2
3
4
5
6
7
8
9
10
11
12
13
14
func main() {
// 当root=/tmp时,不会遍历目录下的文件
err := filepath.Walk("/tmp/", walkFunc)
if err != nil {
fmt.Printf("File walk error: %v\n", err)
}
}

func walkFunc(path string, info os.FileInfo, err error) error {
fmt.Println(path)
//fmt.Println(info.Name(), info.Size())

return nil
}

7. 压缩文件

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
func main() {
filePath := "/tmp/"

filename := filepath.Base(filePath)
fmt.Println(filename)

currentTime := time.Now()
ms := currentTime.Nanosecond() / 1e6
zipFilename := fmt.Sprintf("%s_%s%03d.zip", strings.Split(filename, ".")[0],
currentTime.Format("20060102150405"), ms)
fmt.Println(zipFilename)

ZIP(filePath, zipFilename)
}

func ZIP(source, target string) error {
zipFile, err := os.Create(target)
if err != nil {
return err
}
defer zipFile.Close()

archive := zip.NewWriter(zipFile)
defer archive.Close()

err = filepath.Walk(source, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}

header, err := zip.FileInfoHeader(info)
if err != nil {
return err
}

header.Name = strings.TrimPrefix(path, source+"/")

// 目录不需要压缩
if info.IsDir() {
header.Name += "/"
} else {
// 压缩算法
header.Method = zip.Deflate
}

// 保留文件时间
header.Modified = time.Unix(info.ModTime().Unix(), 0)

// 创建:压缩包头信息
writer, err := archive.CreateHeader(header)
if err != nil {
return err
}

// 目录只需创建,不做其他操作
if info.IsDir() {
return nil
}

// 打开需要压缩的文件
file, err := os.Open(path)
if err != nil {
return nil
}
defer file.Close()

// 压缩文件
_, err = io.Copy(writer, file)

return err
})

return err
}

8. 文件读取的三种方式

  • 文件整体读取
  • 文件分片读取 (块级读取)
  • 文件行级读取

8.1 文件整体读取

1
2
3
4
5
6
7
8
9
10
11
// 方式1:
bs, err := ioutil.ReadFile(filePath)

// 方式2:
file, err := os.Open(filePath)
fileInfo, err := file.Stat()

buffer := make([]byte, fileInfo.Size())
n, err := file.Read(buffer)

fmt.Printf("%s", buffer[:n])

8.2 文件分片读取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
file, err := os.Open(filePath)

buffer := make([]byte, 1024)

for {
n, err := file.Read(buffer)
if err != nil && err != io.EOF {
panic(error)
}

if n == 0 {
break
}

fmt.Printf("%s", buffer)
}

8.3 文件按行读取

1
2
3
4
5
6
7
8
9
10
11
12
file, err := os.Open(filePath)

reader := bufio.NewReader(file)

for {
line, _, err := reader.ReadLine()
if err == io.EOF {
break
}

fmt.Printf("%s", line)
}

9. 文件写入的四周方式

  • 简单覆盖写入
  • 常规文件写入
  • 带缓冲的写入
  • 复制文件写入

9.1 简单覆盖写入

1
err := ioutil.WriteFile(filePath, data, 0666)

9.2 常规文件写入

1
2
3
4
5
6
file, err := os.Create(filePath)
file, err := os.OpenFile(filePath, os.O_RDONLY|os.O_CREATE|os.O_APPEND, 0666)

n, err := file.Write([]byte(data))

n, err := file.WriteString(data)

9.3 带缓冲的写入

bufio 库:

1
2
3
4
5
6
7
8
9
func NewWriter(w io.Writer) *Writer
func NewWriterSize(w io.Writer, size int) *Writer

func (b *Writer) Write(p []byte) (nn int, err error)
func (b *Writer) WriteString(s string) (int, error)
func (b *Writer) WriteByte(c byte) error
func (b *Writer) WriteRune(r rune) (size int, err error)

func (b *Writer) Flush() error

9.4 复制文件写入

io

1
2
3
4
5
// 默认缓冲区大小
func Copy(dst Writer, src Reader) (written int64, err error){}

// 自定义缓冲区大小
func CopyBuffer(dst Writer, src Reader, buf []byte) (written int64, err error) {}

10. io.Reader 接口

Go_io_Reader