go.io

bc75225ef044d29d1f2d1c051d9b8063

任何类型,只要实现了 Reader接口的 Read 方法,那么他就是一个Reader 类型。
Writer 同样如此
还有 ReadCloser 和 ReadWriter

type Reader interface {
    Read(p []byte) (n int, err error)   // 将 len(p) 个字节读取到 p 数组里。返回读取的字节数。
}

type Writer interface {
    Write(p []byte) (n int, err error)
}

// 写入并关闭
type WriteCloser interface {
    Writer
    Closer
}

一些快速创建Reader的方法:

// 从字符串创建一个Reader
r := strings.NewReader("some io.Reader stream to be read\n")
lr := io.LimitReader(r, 4)

// 从一个字节数组创建一个Reader => NewReader returns a new Reader reading from b. 
b = []byte("abc")
bytes.NewReader(b)

// os.Stdout 本书就是一个Writer
if _, err := io.Copy(os.Stdout, r); err != nil {
        log.Fatal(err)
}

N种方式实现读取文件内容

func main() {
    osReadFile()
    // ioutil.ReadFile 就等价于 os.ReadFile,二者是完全一致的

    // ioutil直接一次性读取
    ioutilReadFile()

    // 先打开文件,再用 ioutil 一次性读取
    ioutilReadAll()

    // 一行一行读取
    readLines()

    // 也是一次读取一行,不过通过 ReadString 返回的是字符串
    bufioReadString()

    //每次只读取固定字节数
    readFixedSizeBytes()
}

func readLines() {
    fmt.Println("一次读取一行(从缓冲区): ")
    file, err := os.Open(filename)
    if err != nil {
        panic(err)
    }
    rb := bufio.NewReader(file) // 多了个缓冲区,磁盘读取次数减少
    for {
        lineBytes, err := rb.ReadBytes('\n') // 每次读取到换行,也就是每次读取一行
        if err != nil && err != io.EOF {
            panic(err)
        }

        if err == io.EOF { // 到文件结束停止
            break
        }

        fmt.Printf("Line: %s", lineBytes) // 字符串里已经有换行符,这里不要加换行符
    }
}

func ioutilReadAll() {
    fmt.Println("ioutil 一次性全部读取:")
    fh, err := os.Open(filename)
    if err != nil {
        panic(err)
    }

    // fh 类型为 File, File 实现了Reader 接口
    content3, err := ioutil.ReadAll(fh)
    if err != nil {
        panic(err)
    }
    println(string(content3))
}

func osReadFile() {
    fmt.Println("一次性读取文件内容:对于小文件很方便,但大文件不适用")
    content, err := os.ReadFile(filename)
    if err != nil {
        panic(err)
    }
    fmt.Printf("%s\n", content)
}

func ioutilReadFile() {
    fmt.Println("ioutil.ReadFile 与 os.ReadFile 底层实现是一样的")
    content2, err := ioutil.ReadFile(filename)
    if err != nil {
        panic(err)
    }
    fmt.Printf("ioutil.ReadFile:  %s\n", content2)
}

func readFixedSizeBytes() {
    fmt.Println("一次性读取固定字节的数据(1024): ")
    file, err := os.Open(filename)

    if err != nil {
        panic(err)
    }

    r := bufio.NewReader(file)
    // 每次读取 1024 个字节
    buf := make([]byte, 1024)
    for {
        n, err := r.Read(buf)
        if err != nil && err != io.EOF {
            panic(err)
        }

        if n == 0 {
            break
        }
        fmt.Println("fixed bytes: ", string(buf[:n]))

    }
}

func bufioReadString() {
    fmt.Println("也是一次读取一行,不过通过 ReadString 返回的是字符串 ")
    file, err := os.Open(filename)

    if err != nil {
        panic(err)
    }

    r := bufio.NewReader(file)

    for {
        line, err := r.ReadString('\n')
        line = strings.TrimSpace(line)
        if err != nil && err != io.EOF {
            panic(err)
        }
        if err == io.EOF {
            break
        }
        fmt.Println("bufio.line: ", line)
    }
}

Leave a Comment

Your email address will not be published. Required fields are marked *

PHP 8.1.1 - 19.933 ms, 0 Q