Please enable Javascript to view the contents

Golang文件读写

 ·  ☕ 6 分钟

Golang 的文件读写

读文件

 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

/**
 * @Description:读取指定文件的几种方法,需要注意的是[]byte类型在转换成string类型的时候,都会在最后多一行空格,需要使用result := strings.Replace(string(contents),"\n","",1) 方式替换换行符
 */
package main
import (
    "fmt"
    "io/ioutil"
    "strings"
    "os"
    "strconv"
    "bufio"
)

func main() {
   Ioutil("mytestfile.txt")
   OsIoutil("mytestfile.txt")
   FileRead("mytestfile.txt")
   BufioRead("mytestfile.txt")
}


func Ioutil(name string) {
    if contents,err := ioutil.ReadFile(name);err == nil {
        //因为contents是[]byte类型,直接转换成string类型后会多一行空格,需要使用strings.Replace替换换行符
        result := strings.Replace(string(contents),"\n","",1)
        fmt.Println("Use ioutil.ReadFile to read a file:",result)
    }
}

func OsIoutil(name string) {
      if fileObj,err := os.Open(name);err == nil {
      //if fileObj,err := os.OpenFile(name,os.O_RDONLY,0644); err == nil {
        defer fileObj.Close()
        if contents,err := ioutil.ReadAll(fileObj); err == nil {
            result := strings.Replace(string(contents),"\n","",1)
            fmt.Println("Use os.Open family functions and ioutil.ReadAll to read a file :",result)
            }

        }
}


func FileRead(name string) {
    if fileObj,err := os.Open(name);err == nil {
        defer fileObj.Close()
        //在定义空的byte列表时尽量大一些,否则这种方式读取内容可能造成文件读取不完整
        buf := make([]byte, 1024)
        if n,err := fileObj.Read(buf);err == nil {
               fmt.Println("The number of bytes read:"+strconv.Itoa(n),"Buf length:"+strconv.Itoa(len(buf)))
               result := strings.Replace(string(buf),"\n","",1)
               fmt.Println("Use os.Open and File's Read method to read a file:",result)
            }
    }
}

func BufioRead(name string) {
    if fileObj,err := os.Open(name);err == nil {
        defer fileObj.Close()
        //一个文件对象本身是实现了io.Reader的 使用bufio.NewReader去初始化一个Reader对象,存在buffer中的,读取一次就会被清空
        reader := bufio.NewReader(fileObj)
        //使用ReadString(delim byte)来读取delim以及之前的数据并返回相关的字符串.
        if result,err := reader.ReadString(byte('@'));err == nil {
            fmt.Println("使用ReadSlince相关方法读取内容:",result)
        }
        //注意:上述ReadString已经将buffer中的数据读取出来了,下面将不会输出内容
        //需要注意的是,因为是将文件内容读取到[]byte中,因此需要对大小进行一定的把控
        buf := make([]byte,1024)
        //读取Reader对象中的内容到[]byte类型的buf中
        if n,err := reader.Read(buf); err == nil {
            fmt.Println("The number of bytes read:"+strconv.Itoa(n))
            //这里的buf是一个[]byte,因此如果需要只输出内容,仍然需要将文件内容的换行符替换掉
            fmt.Println("Use bufio.NewReader and os.Open read file contents to a []byte:",string(buf))
        }


    }
}

写文件

 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

/**
 * @Description:使用多种方式将数据写入文件
 */
package main
import (
    "os"
    "io"
    "fmt"
    "io/ioutil"
    "bufio"
)

func main() {
      name := "testwritefile.txt"
      content := "Hello, sss.github.io!\n"
      WriteWithIoutil(name,content)
      contents := "Hello, sss\n"
      //清空一次文件并写入两行contents
      WriteWithFileWrite(name,contents)
      WriteWithIo(name,content)
      //使用bufio包需要将数据先读到buffer中,然后在flash到磁盘中
      WriteWithBufio(name,contents)
}

//使用ioutil.WriteFile方式写入文件,是将[]byte内容写入文件,如果content字符串中没有换行符的话,默认就不会有换行符
func WriteWithIoutil(name,content string) {
    data :=  []byte(content)
    if ioutil.WriteFile(name,data,0644) == nil {
        fmt.Println("写入文件成功:",content)
        }
    }

//使用os.OpenFile()相关函数打开文件对象,并使用文件对象的相关方法进行文件写入操作
//清空一次文件
func WriteWithFileWrite(name,content string){
    fileObj,err := os.OpenFile(name,os.O_RDWR|os.O_CREATE|os.O_TRUNC,0644)
    if err != nil {
        fmt.Println("Failed to open the file",err.Error())
        os.Exit(2)
    }
    defer fileObj.Close()
    if _,err := fileObj.WriteString(content);err == nil {
        fmt.Println("Successful writing to the file with os.OpenFile and *File.WriteString method.",content)
    }
    contents := []byte(content)
    if _,err := fileObj.Write(contents);err == nil {
        fmt.Println("Successful writing to thr file with os.OpenFile and *File.Write method.",content)
    }
}


//使用io.WriteString()函数进行数据的写入
func WriteWithIo(name,content string) {
    fileObj,err := os.OpenFile(name,os.O_RDWR|os.O_CREATE|os.O_APPEND,0644)
    if err != nil {
        fmt.Println("Failed to open the file",err.Error())
        os.Exit(2)
    }
    if  _,err := io.WriteString(fileObj,content);err == nil {
        fmt.Println("Successful appending to the file with os.OpenFile and io.WriteString.",content)
    }
}

//使用bufio包中Writer对象的相关方法进行数据的写入
func WriteWithBufio(name,content string) {
    if fileObj,err := os.OpenFile(name,os.O_RDWR|os.O_CREATE|os.O_APPEND,0644);err == nil {
        defer fileObj.Close()
        writeObj := bufio.NewWriterSize(fileObj,4096)
        //
       if _,err := writeObj.WriteString(content);err == nil {
              fmt.Println("Successful appending buffer and flush to file with bufio's Writer obj WriteString method",content)
           }

        //使用Write方法,需要使用Writer对象的Flush方法将buffer中的数据刷到磁盘
        buf := []byte(content)
        if _,err := writeObj.Write(buf);err == nil {
            fmt.Println("Successful appending to the buffer with os.OpenFile and bufio's Writer obj Write method.",content)
            if  err := writeObj.Flush(); err != nil {panic(err)}
            fmt.Println("Successful flush the buffer data to file ",content)
        }
        }
}

ioutil 读写文件

读文件:

 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\xxxxx\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

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
42
43

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
100
101
102
103
104
105

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*8)
	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, 8192*2*2)
	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 := "./ideaIU-2017.2.7.dmg"

	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))

}

总结

读取文件的方式

读文件方式一:利用ioutil.ReadFile直接从文件读取到[]byte中
读文件方式二:先从文件读取到file中,在从file读取到buf, buf在追加到最终的[]byte
读文件方式三:先从文件读取到file, 在从file读取到缓冲Reader中,从缓冲Reader读取到buf, buf最终追加到[]byte
读文件方式四:读取到file中,再利用ioutil将file直接读取到[]byte中

写文件

写文件方式一:使用 io.WriteString 写入文件
写文件方式二:使用 ioutil.WriteFile 写入文件
写文件方式三:使用 File(Write,WriteString) 写入文件
写文件方式四:使用 bufio.NewWriter 写入文件

目录的操作

目录的创建操作 os.Mkdir os.MkdirAll
目录的删除操作 os.Remove os.RemoveAll

文件的复制

io.Copy(dst, src)

文件操作模式

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

const (
    //只读模式
    O_RDONLY    int    = syscall.O_RDONLY    // open the file read-only.
    //只写模式
    O_WRONLY    int    = syscall.O_WRONLY    // open the file write-only.
    //可读可写
    O_RDWR        int    = syscall.O_RDWR    // open the file read-write.
    //追加内容
    O_APPEND    int    = syscall.O_APPEND    // append data to the file when writing.
    //创建文件,如果文件不存在
    O_CREATE    int    = syscall.O_CREAT    // create a new file if none exists.
    //与创建文件一同使用,文件必须存在
    O_EXCL        int    = syscall.O_EXCL    // used with O_CREATE, file must not exist
    //打开一个同步的文件流
    O_SYNC        int    = syscall.O_SYNC    // open for synchronous I/O.
    //如果可能,打开时缩短文件
    O_TRUNC        int    = syscall.O_TRUNC    // if possible, truncate file when opened.
)