• Go:文件操作


    一、打开文件和关闭文件

    os包File结构体的两个方法:

    func Open(name string) (file *File, err error)
    

    Open打开一个文件用于读取。如果操作成功,返回的文件对象的方法可用于读取数据;对应的文件描述符具有O_RDONLY模式。如果出错,错误底层类型是*PathError。

    func (f *File) Close() error
    

    Close关闭文件f,使文件不能用于读写。它返回可能出现的错误。

    import (
        "fmt"
        "os"
    )
    
    func main() {
        // 打开文件
        file, err := os.Open("e:/a.txt")
        if err != nil {
            fmt.Printf("打开文件出错:%v
    ", err)
        }
        fmt.Println(file) // &{0xc00006a780}
        // 关闭文件
        err = file.Close()
        if err != nil {
            fmt.Printf("关闭文件出错:%v
    ", err)
        }
    }
    View Code

    二、读文件

    读取文件内容并显示在终端

    方式一:(带缓冲方式)

    import (
        "bufio"
        "fmt"
        "io"
        "os"
    )
    
    func main() {
        // 打开文件
        file, err := os.Open("e:/a.txt")
        if err != nil {
            fmt.Printf("打开文件出错:%v
    ", err)
        }
        // 及时关闭文件句柄
        defer file.Close()
        // bufio.NewReader(rd io.Reader) *Reader
        reader := bufio.NewReader(file)
        // 循环读取文件的内容
        for {
            line, err := reader.ReadString('
    ') // 读到一个换行符就结束
            if err == io.EOF { // io.EOF表示文件的末尾
                break
            }
            // 输出内容
            fmt.Print(line)
        }
    }
    View Code

    方式二:一次性将整个文件读入到内存中,这种方式适用于文件不大的情况。(使用 io/ioutil.ReadFile 方法)

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

    ReadFile 从filename指定的文件中读取数据并返回文件的内容。成功的调用返回的err为nil而非EOF。因为本函数定义为读取整个文件,它不会将读取返回的EOF视为应报告的错误。

    import (
        "fmt"
        "io/ioutil"
    )
    
    func main() {
        // 使用 io/ioutil.ReadFile 方法一次性将文件读取到内存中
        filePath := "e:/.txt"
        content, err := ioutil.ReadFile(filePath)
        if err != nil {
            // log.Fatal(err)
            fmt.Printf("读取文件出错:%v", err)
        }
        fmt.Printf("%v
    ", content)
        fmt.Printf("%v
    ", string(content))
    }
    View Code

    三、写文件

    func OpenFile(name string, flag int, perm FileMode) (file *File, err error)

    OpenFile是一个更一般性的文件打开函数,大多数调用者都应用Open或Create代替本函数。它会使用指定的选项(如O_RDONLY等)、指定的模式(如0666等)打开指定名称的文件。如果操作成功,返回的文件对象可用于I/O。如果出错,错误底层类型是*PathError。

    1. 参数二:文件打开模式(可以组合);
    2. 参数三:用来在linux、unix系统下进行权限控制的。

    os包的一些常量:

    const (
        O_RDONLY int = syscall.O_RDONLY // 只读模式打开文件
        O_WRONLY int = syscall.O_WRONLY // 只写模式打开文件
        O_RDWR   int = syscall.O_RDWR   // 读写模式打开文件
        O_APPEND int = syscall.O_APPEND // 写操作时将数据附加到文件尾部
        O_CREATE int = syscall.O_CREAT  // 如果不存在将创建一个新文件
        O_EXCL   int = syscall.O_EXCL   // 和O_CREATE配合使用,文件必须不存在
        O_SYNC   int = syscall.O_SYNC   // 打开文件用于同步I/O
        O_TRUNC  int = syscall.O_TRUNC  // 如果可能,打开时清空文件
    )

    写文件操作应用实例

    示例一:

    1. 创建一个新文件,写入3行:"Hello World"
    2. 打开一个存在的文件,将原来的内容覆盖成新的内容,3行:"你好,世界"
    3. 打开一个存在的文件,在原来的内容基础上,追加3行:"你好,Golang"
    4. 打开一个存在的文件,将原来的内容读出显示在终端,并且追加3行:"你好,World"
    import (
        "bufio"
        "fmt"
        "os"
    )
    
    func main() {
        filePath := "e:/a.txt" // 此文件事先不存在
        file, err := os.OpenFile(filePath, os.O_WRONLY | os.O_CREATE, 0666) // O_CREATE 能创建文件
        if err != nil {
            fmt.Printf("打开文件出错:%v", err)
            return
        }
        // 及时关闭文件句柄
        defer file.Close()
        // 准备写入的内容
        str := "Hello World
    "
        // 写入时,使用带缓冲方式的 bufio.NewWriter(w io.Writer) *Writer
        writer := bufio.NewWriter(file)
        // 使用for循环写入内容
        for i := 0; i < 3; i++ {
            _, err := writer.WriteString(str) // func (b *Writer) WriteString(s string) (int, error)
            if err != nil {
                fmt.Printf("文件写入出错:%s", err)
            }
        }
        // 因为 writer 是带缓存的,所以需要 Flush 方法将缓冲中的数据真正写入到文件中
        _ = writer.Flush()
    }
    1

    2:在1中修改,将 O_CREATE 修改为 O_TRUNC 模式即可,表示:打开文件并清空内容

    3:在2中修改,将 O_TRUNC 修改为 O_APPEND 模式即可,表示:打开文件并在最后追加内容

    import (
        "bufio"
        "fmt"
        "io"
        "os"
    )
    
    func main() {
        filePath := "e:/a.txt"
        file, err := os.OpenFile(filePath, os.O_RDWR | os.O_APPEND, 0666)
        if err != nil {
            fmt.Printf("打开文件出错:%v", err)
            return
        }
        defer file.Close()
    
        // 先读取原来文件的内容,并显示在终端
        reader := bufio.NewReader(file)
        for {
            str, err := reader.ReadString('
    ') // 读到一个换行符就结束
            if err == io.EOF { // io.EOF表示文件的末尾
                break
            }
            // 输出内容
            fmt.Print(str)
        }
    
        // 准备写入的内容
        str := "你好,World
    "
        // 写入时,使用带缓冲方式的 bufio.NewWriter(w io.Writer) *Writer
        writer := bufio.NewWriter(file)
        // 使用for循环写入内容
        for i := 0; i < 3; i++ {
            _, err := writer.WriteString(str) // func (b *Writer) WriteString(s string) (int, error)
            if err != nil {
                fmt.Printf("文件写入出错:%s", err)
            }
        }
        // 因为 writer 是带缓存的,所以需要 Flush 方法将缓冲中的数据真正写入到文件中
        _ = writer.Flush()
    }
    4:读写模式(O_RDWR)

    示例二:将一个文件内容,写入到另一个文件中。(这两个文件已存在)

    这里使用 io/ioutil 的两个方法,ReadFile 和 WriteFile:

    import (
        "fmt"
        "io/ioutil"
    )
    
    func main() {
        filePath1 := "e:/a.txt"
        filePath2 := "e:/b.txt"
        content, err := ioutil.ReadFile(filePath1)
        if err != nil {
            fmt.Printf("读取文件出错:%v", err)
            return
        }
        err = ioutil.WriteFile(filePath2, content, 0666)
        if err != nil {
            fmt.Printf("写入文件出错:%v", err)
            return
        }
    }
    View Code

    四、判断文件是否存在

    golang判断文件或文件夹是否存在的方法为使用 os.Stat() 函数返回的错误值进行判断:

    1. 如果返回的错误为 nil,说明文件或文件夹存在;
    2. 如果返回的错误类型使用 os.IsNotExist() 判断为 true,说明文件或文件夹不存在;
    3. 如果返回的错误为其他类型,则不确定是否存在。
    package main
    
    import (
        "fmt"
        "os"
    )
    
    // 判断文件或文件夹是否存在
    func PathExist(path string) (bool, error) {
        _, err := os.Stat(path)
        if err == nil {
            return true, nil
        }
        if os.IsNotExist(err) {
            return false, nil
        }
        return false, err
    }
    
    func main() {
        filePath := "e:/a.txt"
        flag, err := PathExist(filePath)
        if err != nil {
            fmt.Println(err)
        }
        fmt.Println(flag) // true
    }
    自己写一个函数判断

    五、拷贝文件(带缓冲方式)

    使用 io/Copy 函数:

    func Copy(dst Writer, src Reader) (written int64, err error)
    

    将src的数据拷贝到dst,直到在src上到达EOF或发生错误。返回拷贝的字节数和遇到的第一个错误。

    对成功的调用,返回值err为nil而非EOF,因为Copy定义为从src读取直到EOF,它不会将读取到EOF视为应报告的错误。如果src实现了WriterTo接口,本函数会调用src.WriteTo(dst)进行拷贝;否则如果dst实现了ReaderFrom接口,本函数会调用dst.ReadFrom(src)进行拷贝。

    package main
    
    import (
        "bufio"
        "fmt"
        "io"
        "os"
    )
    
    // 将 srcFilePath 拷贝到 dstFilePath
    func CopyFile(dstFilePath string, srcFilePath string) (written int64, err error) {
        // 打开srcFilePath
        srcFile, err := os.Open(srcFilePath)
        if err != nil {
            fmt.Printf("打开文件出错:%s
    ", err)
            return
        }
        defer srcFile.Close()
        // 通过 bufio/NewReader,传入 srcFile,获取到 reader
        reader := bufio.NewReader(srcFile)
        // 打开dstFilePath
        dstFile, err := os.OpenFile(dstFilePath, os.O_WRONLY | os.O_CREATE, 0666)
        if err != nil {
            fmt.Printf("打开文件出错:%s
    ", err)
            return
        }
        defer dstFile.Close()
        // 通过 bufio/NewWriter,传入 dstFile,获取到 writer
        writer := bufio.NewWriter(dstFile)
        return io.Copy(writer, reader)
    }
    
    func main() {
        srcFilePath := "e:/a.mp4"
        dstFilePath := "f:/b.mp4"
        _, err := CopyFile(dstFilePath, srcFilePath)
        if err != nil {
            fmt.Printf("拷贝文件出错:%s", err)
        }
        fmt.Println("拷贝文件完成")
    }
    自己写一个函数完成拷贝文件

    六、遍历一个目录

    package main
    
    import (
        "fmt"
        "os"
    )
    
    func main() {
        fmt.Println("请输入一个目录的路径:")
        var path string
        _, _ = fmt.Scan(&path)
        // 打开目录
        f, err := os.OpenFile(path, os.O_RDONLY, os.ModeDir)
        if err != nil {
            fmt.Printf("Open file failed:%s.
    ", err)
            return
        }
        defer f.Close()
        // 读取目录
        info, err := f.Readdir(-1) // -1 表示读取目录中所有目录项
        // 遍历返回的切片
        for _, fileInfo := range info {
            if fileInfo.IsDir() {
                fmt.Printf("%s是一个目录
    ", fileInfo.Name())
            } else {
                fmt.Printf("%s是一个文件
    ", fileInfo.Name())
            }
        }
    }
    View Code

    七、其他

    统计一个文件中含有的英文、数字、空格以及其他字符数量。

    package main
    
    import (
        "bufio"
        "fmt"
        "io"
        "os"
    )
    
    // 定义一个结构体,用于保存统计结果
    type CharCount struct {
        AlphaCount     int // 记录英文个数
        NumCount     int // 记录数字的个数
        SpaceCount     int // 记录空格的个数
        OtherCount     int // 记录其它字符的个数
    }
    
    func main() {
        // 思路: 打开一个文件, 创一个 reader
        // 每读取一行,就去统计该行有多少个 英文、数字、空格和其他字符
        // 然后将结果保存到一个结构体
        filePath := "e:/a.txt"
        file, err := os.Open(filePath)
        if err != nil {
            fmt.Printf("打开文件出错:%s
    ", err)
            return
        }
        defer file.Close()
        // 定义一个 CharCount 实例
        var count CharCount
        //创建一个Reader
        reader := bufio.NewReader(file)
        // 开始循环的读取文件的内容
        for {
            line, err := reader.ReadString('
    ')
            if err == io.EOF { // 读到文件末尾就退出
                break
            }
            // 遍历每一行(line),进行统计
            for _, v := range line {
                switch {
                    case v >= 'a' && v <= 'z':
                        fallthrough // 穿透
                    case v >= 'A' && v <= 'Z':
                        count.AlphaCount++
                    case v >= '0' && v <= '9':
                        count.NumCount++
                    case v == ' ' || v == '	':
                        count.SpaceCount++
                    default :
                        count.OtherCount++
                }
            }
        }
        // 输出统计的结果看看是否正确
        fmt.Printf("字符的个数为:%v
    数字的个数为:%v
    空格的个数为:%v
    其它字符个数:%v
    ",
            count.AlphaCount, count.NumCount, count.SpaceCount, count.OtherCount)
    }
    View Code
  • 相关阅读:
    Ubuntu16.04 中 Vscode 如何断点调试C语言程序
    PHP疑难杂症
    PHP之外观模式
    23种设计模式之适配器模式(Adapter Pattern)
    23种设计模式之原型模式(Prototype Pattern)
    23种设计模式之单例(Singleton Pattern)
    23种设计模式之抽象工厂(Abstract Factory Pattern)
    23种设计模式之工厂方法(Factory Method Pattern)
    简单工厂
    Nosql之Redis
  • 原文地址:https://www.cnblogs.com/believepd/p/10951763.html
Copyright © 2020-2023  润新知