本文对golang的读写文件的操作进行展示废话少说直接上代码:

package main

import (
    "bufio"
    "errors"
    "fmt"
    "io"
    "log"
    "os"
)

// 读取文件的各种方式
//
// 运行方式: go build main.go; ./main.exe

// * 整个文件读到内存,适用于文件较小的情况
func readAllIntoMemory(filename string) (content []byte, err error) {
    fp, err := os.Open(filename) // 获取文件指针
    if err != nil {
        return nil, err
    }
    defer fp.Close()

    fileInfo, err := fp.Stat()
    if err != nil {
        return nil, err
    }
    buffer := make([]byte, fileInfo.Size())
    _, err = fp.Read(buffer) // 文件内容读取到buffer中
    if err != nil {
        return nil, err
    }
    return buffer, nil
}

// * 一块一块地读取, 即给一个缓冲, 分多次读到缓冲中
func readByBlock(filename string) (content []byte, err error) {
    fp, err := os.Open(filename) // 获取文件指针
    if err != nil {
        return nil, err
    }
    defer fp.Close()

    const bufferSize = 64 // 缓冲大小, 每次读取64个字节

    buffer := make([]byte, bufferSize)
    for {
        // 注意这里要取bytesRead, 否则有问题
        bytesRead, err := fp.Read(buffer) // 文件内容读取到buffer中
        content = append(content, buffer[:bytesRead]...)
        if err != nil {
            if err == io.EOF {
                err = nil
                break
            } else {
                return nil, err
            }
        }
    }
    return
}

// 逐行读取, 一行是一个[]byte, 多行就是[][]byte
func readByLine(filename string) (lines [][]byte, err error) {
    fp, err := os.Open(filename) // 获取文件指针
    if err != nil {
        return nil, err
    }
    defer fp.Close()
    bufReader := bufio.NewReader(fp)

    for {
        line, _, err := bufReader.ReadLine()
        if err != nil {
            if err == io.EOF {
                err = nil
                break
            }
        } else {
            lines = append(lines, line)
        }
    }

    return
}

// * simulate tail -n -f filename
func readLikeTail(filename string, n int) (lines [][]byte, err error) {
    if n <= 0 {
        return nil, errors.New("argument error")
    }
    fp, err := os.Open(filename) // 获取文件指针
    if err != nil {
        return nil, err
    }
    defer fp.Close()

    offset, err := fp.Seek(0, io.SeekEnd)
    if err != nil {
        return nil, err
    }

    buffer := make([]byte, 1)
    count := 0
    for offset > 0 {
        offset--
        bytesRead, err := fp.ReadAt(buffer, offset)
        if err != nil {
            return nil, err
        }

        if buffer[0] == '\n' { // 读到了一行
            count++
            lines = append(lines, buffer[:bytesRead])
            if count == n {
                break
            }
        }

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

    return
}

func main() {
    const testFileName = "ls-al.txt"
    // fmt.Println(file.GetCurrentDirectory())

    // *
    content, err := readAllIntoMemory(testFileName)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("%s\n", content)

    // *
    content, err = readByBlock(testFileName)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("%s\n", content)

    // *
    lines, err := readByLine(testFileName)
    if err != nil {
        log.Fatal(err)
    }
    for i, line := range lines {
        fmt.Printf("readByLine: %d %s\n", i+1, line)
    }

    // *
    fmt.Println()
    lines, err = readLikeTail(testFileName, 3)
    for i, line := range lines {
        fmt.Printf("readLikeTail: %d %s\n", i+1, line)
    }
}

写文件的操作:

 

func writeToFile(msg string)  {
    f, err := os.OpenFile("/home/mingbai/del/koala.log", os.O_WRONLY&os.O_CREATE, 0666)
    if err != nil {
        log.Println(err.Error())
    }

    _, err = f.Write([]byte(msg))
    if err != nil {
        log.Println(err.Error())
    }
    f.Close()
}

 解释:

OpenFile 这个函数不那么好理解,解释一下. 第一个参数 就是文件路径.

第二个参数是一个 文件打开方式的flag是读是写 还是读写;是追加还是清空等, 第一种类型同第二种类型可用'|' (与或非的或)操作连接,表示两个都要. 其实你还可以加三个,比如:os.O_WRONLY|os.O_CREATE|os.O_APPEND 表示写模式打开,没有则创建且追加的方式写入.

第三个参数是操作文件的权限, 就是Linux 文件权限的那种4 读,2 写, 1 执行; 可累加.比较常见,不多解释了.