golang 读取文件

一、打开文件的四种方式

(1) 利用ioutil.ReadFile直接从文件读取到[]byte中

func Read0()  (string){
    f, err := ioutil.ReadFile("file/test")
    if err != nil {
        fmt.Println("read fail", err)
    }
    return string(f)
}

(2) 先从文件读取到file中,在从file读取到buf, buf在追加到最终的[]byte

func Read1()  (string){
    //获得一个file
    f, err := os.Open("file/test")
    if err != nil {
        fmt.Println("read fail")
        return ""
    }

    //把file读取到缓冲区中
    defer f.Close()
    var chunk []byte
    buf := make([]byte, 1024)

    for {
        //从file读取到buf中
        n, err := f.Read(buf)
        if err != nil && err != io.EOF{
            fmt.Println("read buf fail", err)
            return ""
        }
        //说明读取结束
        if n == 0 {
            break
        }
        //读取到最终的缓冲区中
        chunk = append(chunk, buf[:n]...)
    }

    return string(chunk)
    //fmt.Println(string(chunk))
}

(3) 先从文件读取到file, 在从file读取到Reader中,从Reader读取到buf, buf最终追加到[]byte

//先从文件读取到file, 在从file读取到Reader中,从Reader读取到buf, buf最终追加到[]byte,这个排第三
func Read2() (string) {
    fi, err := os.Open("file/test")
    if err != nil {
        panic(err)
    }
    defer fi.Close()

    r := bufio.NewReader(fi)
    var chunks []byte

    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))
        chunks = append(chunks, buf...)
    }
    return string(chunks)
    //fmt.Println(string(chunks))
}

(4) 读取到file中,再利用ioutil将file直接读取到[]byte中

//读取到file中,再利用ioutil将file直接读取到[]byte中, 这是最优
func Read3()  (string){
    f, err := os.Open("file/test")
    if err != nil {
        fmt.Println("read file fail", err)
        return ""
    }
    defer f.Close()

    fd, err := ioutil.ReadAll(f)
    if err != nil {
        fmt.Println("read to fd fail", err)
        return ""
    }

    return string(fd)
}

读取速度比较

方式四 > 方式一 > 方式三 > 方式四

二、写文件

(1) 使用 io.WriteString 写入文件

func Write0()  {
    fileName := "file/test1"
    strTest := "测试测试"

    var f *os.File
    var err error

    if CheckFileExist(fileName) {  //文件存在
        f, err = os.OpenFile(fileName, os.O_APPEND, 0666) //打开文件
        if err != nil{
            fmt.Println("file open fail", err)
            return
        }
    }else {  //文件不存在
        f, err = os.Create(fileName) //创建文件
        if err != nil {
            fmt.Println("file create fail")
            return
        }
    }
    //将文件写进去
    n, err1 := io.WriteString(f, strTest)
    if err1 != nil {
        fmt.Println("write error", err1)
        return
    }
    fmt.Println("写入的字节数是:", n)
}

(2) 使用 ioutil.WriteFile 写入文件

func Write1()  {
    fileName := "file/test2"
    strTest := "测试测试"
    var d = []byte(strTest)
    err := ioutil.WriteFile(fileName, d, 0666)
    if err != nil {
        fmt.Println("write fail")
    }
    fmt.Println("write success")
}

(3) 使用 File(Write,WriteString) 写入文件

func Write2()  {

    fileName := "file/test3"
    strTest := "测试测试"
    var d1 = []byte(strTest)

    f, err3 := os.Create(fileName) //创建文件
    if err3 != nil{
        fmt.Println("create file fail")
    }
    defer f.Close()
    n2, err3 := f.Write(d1) //写入文件(字节数组)

    fmt.Printf("写入 %d 个字节n", n2)
    n3, err3 := f.WriteString("writesn") //写入文件(字节数组)
    fmt.Printf("写入 %d 个字节n", n3)
    f.Sync()
}

(4) 使用 bufio.NewWriter 写入文件

func Write3()  {
    fileName := "file/test3"
    f, err3 := os.Create(fileName) //创建文件
    if err3 != nil{
        fmt.Println("create file fail")
    }
    w := bufio.NewWriter(f) //创建新的 Writer 对象
    n4, err3 := w.WriteString("bufferedn")
    fmt.Printf("写入 %d 个字节n", n4)
    w.Flush()
    f.Close()
}

三、检测文件是否存在

func CheckFileExist(fileName string) bool {
    _, err := os.Stat(fileName)
    if os.IsNotExist(err) {
        return false
    }
    return true
}

四、逐行读取文件

    f, err := os.Open("test.txt")
    if err != nil {
        panic(err)
    }
    defer f.Close()

    rd := bufio.NewReader(f)
    for {
        line, err := rd.ReadString('
') //以'
'为结束符读入一行
        
        if err != nil || io.EOF == err {
            break
        }
              fmt.Println(line)
              }

五、os.openfile大文件件方式和模式

方式

// Flags to OpenFile wrapping those of the underlying system. Not all
// flags may be implemented on a given system.
const (
    // Exactly one of O_RDONLY, O_WRONLY, or O_RDWR must be specified.
    // 只读模式
    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.
    // The remaining values may be or'ed in to control behavior.
    // 追加内容
    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  // truncate regular writable file when opened.
)

模式

// The defined file mode bits are the most significant bits of the FileMode.
// The nine least-significant bits are the standard Unix rwxrwxrwx permissions.
// The values of these bits should be considered part of the public API and
// may be used in wire protocols or disk representations: they must not be
// changed, although new bits might be added.
const (
    // The single letters are the abbreviations
    // used by the String method's formatting.
    // 文件夹模式
    ModeDir        FileMode = 1 << (32 - 1 - iota) // d: is a directory
    // 追加模式
    ModeAppend                                     // a: append-only
    // 单独使用
    ModeExclusive                                  // l: exclusive use
    // 临时文件
    ModeTemporary                                  // T: temporary file; Plan 9 only
    // 象征性的关联
    ModeSymlink                                    // L: symbolic link
    // 设备文件
    ModeDevice                                     // D: device file
    // 命名管道
    ModeNamedPipe                                  // p: named pipe (FIFO)
    // Unix 主机 socket
    ModeSocket                                     // S: Unix domain socket
    // 设置uid
    ModeSetuid                                     // u: setuid
    // 设置gid
    ModeSetgid                                     // g: setgid
    // UNIX 字符串设备,当设备模式是设置unix
    ModeCharDevice                                 // c: Unix character device, when ModeDevice is set
    // 粘性的
    ModeSticky                                     // t: sticky
    // 非常规文件;对该文件一无所知
    ModeIrregular                                  // ?: non-regular file; nothing else is known about this file

    // bit位遮盖,不变的文件设置为none
    // Mask for the type bits. For regular files, none will be set.
    ModeType = ModeDir | ModeSymlink | ModeNamedPipe | ModeSocket | ModeDevice | ModeCharDevice | ModeIrregular
    // 权限位
    ModePerm FileMode = 0777 // Unix permission bits
)

创建一个文件并追加

package main

import (
    "os"
)
func main() {
    fname := "/tmp/t.txt"
    f, err := os.OpenFile(fname, os.O_CREATE|os.O_RDWR|os.O_APPEND, os.ModeAppend|os.ModePerm)
    if err != nil {
        fmt.Println(err)
    }
    f.WriteString("test")
    f.Close()
}

参考链接:

https://www.jianshu.com/p/711c453bff16
https://studygolang.com/articles/282
https://www.cnblogs.com/landv/p/13140156.html

原文地址:https://www.cnblogs.com/-xuan/p/14537718.html