一般来说有四种常见的读取文件操作方法:

  • 使用File自带的Read方法
  • 使用bufio库的Read方法
  • 使用io/ioutil库的ReadAll()
  • 使用io/ioutil库的ReadFile()

先说结论:

当每次读取块的大小小于4kb,建议使用bufio.NewReader(f),大于4kb用bufio.NewReaderSize(f,缓存大小)

要读Reader,图方便使用ioutil.ReadAll()

一次性读取文件,使用ioutil.ReadFile()

不建议使用普通的Read

关于性能的深入探究,我会在下篇博文详细探讨

总而言之,要性能使用bufio,方便就用ioutil

下面为各种方法示例

package main

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

type ValNode struct {
    row int
    col int
    val int
}

func main() {
    //1.创建一个原始数组
    var chessMap [11][11]int
    chessMap[1][2] = 1 //黑子
    chessMap[2][3] = 2 //篮子

    //输出看看原始数组
    for _, v := range chessMap {
        for _, v2 := range v {
            fmt.Printf("%d\t", v2)
        }
    }

}

//OS包
func read1(path string) {
    fi, err := os.Open(path)
    if err != nil {
        panic(err)
    }
    defer fi.Close()
    buf := make([]byte, 1024)
    for {
        n, err := fi.Read(buf)
        if err != nil && err != io.EOF {
            panic(err)
        }
        if 0 == n {
            break
        }
        fmt.Println(string(buf[:n]))
    }
}

//bufio包
func read2(path string) {
    fi, err := os.Open(path)
    if err != nil {
        panic(err)
    }
    defer fi.Close()
    r := bufio.NewReader(fi)
    buf := make([]byte, 1024)
    for {
        n, err := r.Read(buf)
        if err != nil && err != io.EOF {
            panic(err)
        }
        if 0 == n {
            break
        }

        fmt.Println(string(buf[:n]))
    }
}

//ioutil包
func read4(path string) {
    r, err := ioutil.ReadFile(path)
    if err != nil {
        panic(err)
    }
    fmt.Println(r)
}

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


OS包详细用法

目录处理

func Mkdir(name string, perm FileMode) error 创建名称为name的目录,权限设置是perm,例如0777

func MkdirAll(path string, perm FileMode) error 根据path创建多级子目录,例如astaxie_test1_test2。

func Remove(name string) error 删除名称为name的目录,当目录下有文件或者其他目录时会出错

func RemoveAll(path string) error 根据path删除多级子目录,如果path是单个名称,那么该目录下的子目录全部删除。

package main

import (
    "fmt"
    "os"
)

func main() {
    os.Mkdir("tmac", 0777)
    os.MkdirAll("tmac/test1/test2", 0777)
    err := os.Remove("tmac")
    if err != nil {
        fmt.Println(err)
    }
    os.RemoveAll("tmac")
}

文件创建

新建文件可以通过如下两个方法

func Create(name string) (file *File, err Error) 根据提供的文件名创建新的文件,返回一个文件对象,默认权限是0666的文件,返回的文件对象是可读写的。

func NewFile(fd uintptr, name string) *File 根据文件描述符创建相应的文件,返回一个文件对象

通过如下两个方法来打开文件:

func Open(name string) (file *File, err Error) 该方法打开一个名称为name的文件,但是是只读方式,内部实现其实调用了OpenFile。

func OpenFile(name string, flag int, perm uint32) (file *File, err Error) 打开名称为name的文件,flag是打开的方式,只读、读写等,perm是权限

写文件

func (file *File) Write(b []byte) (n int, err Error) 写入byte类型的信息到文件

func (file *File) WriteAt(b []byte, off int64) (n int, err Error) 在指定位置开始写入byte类型的信息

func (file *File) WriteString(s string) (ret int, err Error) 写入string信息到文件

读文件

func (file *File) Read(b []byte) (n int, err Error) 读取数据到b中

func (file *File) ReadAt(b []byte, off int64) (n int, err Error) 从off开始读取数据到b中

package main

import (
    "fmt"
    "os"
)

func main() {
    userFile := "tmac.txt"
    fl, err := os.Open(userFile)        
    if err != nil {
        fmt.Println(userFile, err)
        return
    }
    defer fl.Close()
    buf := make([]byte, 1024)
    for {
        n, _ := fl.Read(buf)
        if 0 == n {
            break
        }
        os.Stdout.Write(buf[:n])
    }
}

删除文件

func Remove(name string) Error 调用该函数就可以删除文件名为name的文件

ioutil包详细用法

包名 ”io/ioutil“

func ReadAll(r io.Reader) ([]byte, error)

读取 r 中所有数据并返回

func main() {
    s := strings.NewReader("Hello World!")
    ra, _ := ioutil.ReadAll(s)
    fmt.Printf("%s", ra)
}

func ReadFile(filename string) ([]byte, error)

直接读取文件

func main() {
    ra, _ := ioutil.ReadFile("file path")
    fmt.Printf("%s", ra)
}

func WriteFile(filename string, data []byte, perm os.FileMode) error

WriteFile 向文件 filename 中写入数据 data

如果文件不存在,则以 perm 权限创建该文件

如果文件存在,os.FileMode 不同使用不同的规则

func main() {
    fn := "file path""
    s := []byte("Hello World!")
    ioutil.WriteFile(fn, s, os.ModeAppend)
    rf, _ := ioutil.ReadFile(fn)
    fmt.Printf("%s", rf)
}

func ReadDir(dirname string) ([]os.FileInfo, error)

ReadDir 读取目录 dirmane 中的所有目录和文件(不包括子目录)

返回读取到的文件的信息列表和读取过程中遇到的任何错误

返回的文件列表是经过排序的

func main() {
    rd, err := ioutil.ReadDir("file path")
    for _, fi := range rd {
        fmt.Println("")
        fmt.Println(fi.Name())
        fmt.Println(fi.IsDir())
        fmt.Println(fi.Size())
        fmt.Println(fi.ModTime())
        fmt.Println(fi.Mode())
    }
    fmt.Println("")
    fmt.Println(err)
}

bufio包详细用法

参见这篇博文