Go语言学习#2-文件操作


=Start=

缘由:

最近在跟着郝林老师的《Go语言核心36讲》这门课程重拾Go语言学习(之前在15年的时候我自学过一段时间,不过后来没怎么用Go来写代码,所以有些内容都忘了,这次希望能坚持下去),所以准备把一些常见功能用Go语言试着实践一遍,加强学习效果和对这门语言的感觉。

正文:

参考解答:
如何获取当前运行文件所在的目录及文件名?
package main

import (
    "fmt"
    "log"
    "os"
    "path/filepath"
)

func main() {
    fmt.Printf("Filename: %s\n", os.Args[0])
    fmt.Printf("filepath.Base(): %s\n", filepath.Base(os.Args[0]))
    fmt.Printf("filepath.Dir(): %s\n", filepath.Dir(os.Args[0]))

    dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("filepath.Abs(filepath.Dir()): %s\n", dir)

    // 另一种方法
    ex, err := os.Executable()
    if err != nil {
        panic(err)
    }
    exPath := filepath.Dir(ex)
    fmt.Println()
    fmt.Println(ex)
    fmt.Println(exPath)
}
如何检查一个文件/目录是否存在?
// 检查传入的字符串name所指向的文件或目录是否存在,存在则返回true
func Exists(name string) bool {
    if _, err := os.Stat(name); err != nil {
        if os.IsNotExist(err) {
            return false
        }
    }
    return true
}

但是,下面的这个版本会更好一些(因为多返回了一个error字段):

func Exists(name string) (bool, error) {
    _, err := os.Stat(name)
    if os.IsNotExist(err) {
        return false, nil
    }
    return err != nil, err
}
如何判断一个文件是否是目录?
if stat, err := os.Stat(name); err == nil && stat.IsDir() {
    // name is a directory
}
如何进行文件读写操作?

方法一:基于原生的os.Open/os.Create和Read/Write操作

package main

import (
    "io"
    "os"
)

func main() {
    // open input file
    fi, err := os.Open("input.txt")
    if err != nil {
        panic(err)
    }
    // close fi on exit and check for its returned error
    defer func() {
        if err := fi.Close(); err != nil {
            panic(err)
        }
    }()

    // open output file
    fo, err := os.Create("output.txt")
    if err != nil {
        panic(err)
    }
    // close fo on exit and check for its returned error
    defer func() {
        if err := fo.Close(); err != nil {
            panic(err)
        }
    }()

    // 创建一个1024字节的缓冲区用于临时存放读取的内容
    buf := make([]byte, 1024)
    for {
        // 尝试每次读取1024字节的内容存入缓冲区buf
        n, err := fi.Read(buf)
        if err != nil && err != io.EOF {
            panic(err)
        }
        if n == 0 {
            break
        }

        // 调用Write接口将缓冲区内容写入文件
        if _, err := fo.Write(buf[:n]); err != nil {
            panic(err)
        }
    }
}

方法二:使用bufio

package main

import (
    "bufio"
    "io"
    "os"
)

func main() {
    // 打开输入文件
    fi, err := os.Open("input.txt")
    if err != nil {
        panic(err)
    }
    // 使用defer函数进行文件关闭操作,若关闭失败则抛出panic
    defer func() {
        if err := fi.Close(); err != nil {
            panic(err)
        }
    }()
    // 创建读缓冲
    r := bufio.NewReader(fi)

    // open output file
    fo, err := os.Create("output.txt")
    if err != nil {
        panic(err)
    }
    // close fo on exit and check for its returned error
    defer func() {
        if err := fo.Close(); err != nil {
            panic(err)
        }
    }()
    // 创建写缓冲
    w := bufio.NewWriter(fo)

    // make a buffer to keep chunks that are read
    buf := make([]byte, 1024)
    for {
        // read a chunk
        n, err := r.Read(buf)
        if err != nil && err != io.EOF {
            panic(err)
        }
        if n == 0 {
            break
        }

        // write a chunk
        if _, err := w.Write(buf[:n]); err != nil {
            panic(err)
        }
    }

    if err = w.Flush(); err != nil {
        panic(err)
    }
}

方法三:使用ioutil封装

package main

import (
    "io/ioutil"
)

func main() {
    // 将文件内容一次性读入内存(不适用于大文件)
    b, err := ioutil.ReadFile("input.txt")
    if err != nil {
        panic(err)
    }

    // 将内容一次性写入文件
    err = ioutil.WriteFile("output.txt", b, 0644)
    if err != nil {
        panic(err)
    }
}
Go语言中如何一次读取文件的一行内容?(借助bufio.Scanner
package main

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

func main() {
    file, err := os.Open("/path/to/file.txt")
    if err != nil {
        log.Fatal(err)
    }
    defer file.Close()

    # 可以使用bufio.NewScanner进行一次读取一行处理
    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
        fmt.Println(scanner.Text())
    }

    if err := scanner.Err(); err != nil {
        log.Fatal(err)
    }
}
Go语言中如何处理各类配置文件?

可以通过创建对应格式的结构体struct来进行处理,具体可以参考「How to handle configuration in Go」。

 

参考链接:

=END=

,

《“Go语言学习#2-文件操作”》 有 1 条评论

  1. Go 语言中的文件操作
    https://www.devdungeon.com/content/working-files-go
    http://colobu.com/2016/10/12/go-file-operations/
    `
    介绍
      万物皆文件
    基本操作
      创建空文件
      Truncate文件
      得到文件信息
      重命名和移动
      删除文件
      打开和关闭文件
      检查文件是否存在
      检查读写权限
      改变权限、拥有者、时间戳
      硬链接和软链接
    读写
      复制文件
      跳转到文件指定位置(Seek)
      写文件
      快写文件
      使用缓存写
      读取最多N个字节
      读取正好N个字节
      读取至少N个字节
      读取全部字节
      快读到内存
      使用缓存读
      使用 scanner
    压缩
      打包(zip) 文件
      抽取(unzip) 文件
      压缩文件
      解压缩文件
    其它
      临时文件和目录
      通过HTTP下载文件
      哈希和摘要
    参考
    `

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注