• Go语言之文件操作


    一、文件基本介绍

    文件就是保存数据用的,它可以保存一段文字、一张图片,也可以是声音或者视频等,它在程序中以流的形式来操作。

     os包下的File结构体含了所有的文件相关操作:

    type File struct {
        // 内含隐藏或非导出字段
    }

     File代表一个打开的文件对象。

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

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

    func (f *File) Close() error

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

    ...

    更多查看:https://studygolang.com/static/pkgdoc/pkg/os.htm#File

    二、打开文件及关闭文件

    对文件的操作首先就是打开,其次是操作文件,最后是关闭文件。所以打开和关闭文件必不可少。

    打开和关闭就使用上面提到的

    案例演示:

    package main
    
    import (
        "fmt"
        "os"
    )
    
    func main() {
        // 打开该目录下的1.txt文件
        file, err := os.Open("./1.txt")
        if err != nil {
            fmt.Println("文件打开出错...")
        }
        // 输出文件,它是一个指针
        fmt.Println(file) // &{0xc00007c780}
    
        // 关闭文件
        err = file.Close()
        if err != nil {
            fmt.Println("文件关闭出错...")
        }
    
    }

    三、文件读操作

    • 带缓冲区读操作
    • 一次性读操作

    1、带缓冲区读操作

    带缓冲区读操作,就是讲文件一部分、一部分的进行读取到内存中,适用于大文件,涉及到的函数和方法有:

    • os.Open
    • file.Close
    • bufio.NewReader
    • reader.ReadString

    案例演示:

    package main
    
    import (
        "bufio"
        "fmt"
        "io"
        "os"
    )
    
    func main() {
    
        // 打开一个文件
        file, err := os.Open("./1.txt")
        if err != nil {
            fmt.Println("文件打开出错...")
        }
    
        // 延时关闭文件, 函数执行完毕自动关闭文件
        defer file.Close()
    
        // 文件读操作
        // 返回的是一个*Reader类型的缓冲区, 默认的缓存大小4096
        reader := bufio.NewReader(file)
        // 循环读取文件内容
        for {
            str, err := reader.ReadString('\n')
            if err == io.EOF {
                // io.EOF表示文件末尾,就结束读取
                break
            }
            // 输出每一行内容
            fmt.Println(str)
        }
    
    }

    2、一次性读操作

    一次性读操作适用于小文件,涉及的函数和方法有:

    • ioutil.ReadFile

    这个函数实践文件的打开和关闭封装在内部,所以无需显式的操作。

    案例演示:

    package main
    
    import (
        "fmt"
        "io/ioutil"
    )
    
    func main() {
    
        // 打开一个文件
        content, err := ioutil.ReadFile("./1.txt")
        if err != nil {
            fmt.Println("文件打开出错...")
        }
    
        // 文件读操作
        // content是一个字节切片类型
        fmt.Println(string(content))
    
    }

    四、文件写操作

    (一)os.OpenFile

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

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

    参数说明:

    • name 表示的是文件的路径字符串
    • flag 文件打开模式
    • perm 权限控制,用于Linux中的权限(r-->4、w-->2、x-->1)

    flag可选值:

    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、带缓存的写入

    • 创建文件并写入内容
    package main
    
    import (
        "bufio"
        "fmt"
        "os"
    )
    
    func main() {
    
        filePath := "./2.txt"
        // 只写模式打开文件、如果文件不存在就创建
        file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, 0666)
        if err != nil {
            fmt.Println("文件错误...")
            return
        }
        // 函数执行完毕关闭文件
        defer file.Close()
    
        // 向文件写入内容
        str := "hello world!"
    
        // 使用带缓存的写入
        writer := bufio.NewWriter(file)
        writer.WriteString(str)
    
        // writer带缓存的,所以在调用WriterString方法时,其实
        // 时先写入到缓存中,所以需要调用Flush方法,将缓存中的数据
        // 真正写入到文件,否则文件中没有数据
        writer.Flush()
    
    }
    •  覆盖已经存在的内容
    package main
    
    import (
        "bufio"
        "fmt"
        "os"
    )
    
    func main() {
    
        filePath := "./2.txt"
        // 覆盖已经存在文件中的内容
        file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_TRUNC, 0666)
        if err != nil {
            fmt.Println("文件错误...")
            return
        }
        // 函数执行完毕关闭文件
        defer file.Close()
    
        // 向文件写入内容
        str := "hello iveboy"
    
        // 使用带缓存的写入
        writer := bufio.NewWriter(file)
        writer.WriteString(str)
    
        // writer带缓存的,所以在调用WriterString方法时,其实
        // 时先写入到缓存中,所以需要调用Flush方法,将缓存中的数据
        // 真正写入到文件,否则文件中没有数据
        writer.Flush()
    
    }
    • 读文件于追加内容
    package main
    
    import (
        "bufio"
        "fmt"
        "io"
        "os"
    )
    
    func main() {
    
        filePath := "./2.txt"
        // 覆盖已经存在文件中的内容
        file, err := os.OpenFile(filePath, os.O_RDONLY|os.O_APPEND, 0666)
        if err != nil {
            fmt.Println("文件错误...")
            return
        }
        // 函数执行完毕关闭文件
        defer file.Close()
    
        // 读文件
        reader := bufio.NewReader(file)
        for {
            str, err := reader.ReadString('\n')
            if err == io.EOF {
                fmt.Println("已经读到文件末尾了...")
                break
            }
            fmt.Print(str)
        }
    
        // 向文件中写内容
        str := "hello iveboy"
    
        // 使用带缓存的写入
        writer := bufio.NewWriter(file)
        writer.WriteString(str)
    
        // writer带缓存的,所以在调用WriterString方法时,其实
        // 时先写入到缓存中,所以需要调用Flush方法,将缓存中的数据
        // 真正写入到文件,否则文件中没有数据
        writer.Flush()
    
    }

    2、一次性写入

    将一个文件的内容写入到另一个文件中:

    package main
    
    import (
        "fmt"
        "io/ioutil"
    )
    
    func main() {
        // 1、将已经存在的文件a.txt中的内容读取到内存
        // 2、将内存中的内容写入到文件b.txt
    
        filePath1 := "./a.txt"
        filePath2 := "./b.txt"
    
        // 读取a.txt文件中的内容
        data, err := ioutil.ReadFile(filePath1)
        if err != nil {
            fmt.Println("文件读取错误...")
            return
        }
    
        // 打开写入的文件,如果文件不存在就会创建,然后写入数据
        err = ioutil.WriteFile(filePath2, data, 0666)
        if err != nil {
            fmt.Println("打开写入的文件错误...")
        }
    
    }

    五、文件其它操作 

    1、判断文件是否存在

    golang通过对os.Stat()函数返回的错误值进行判断:

    • 如果返回的错误为nil,则文件或者文件夹存在
    • 如果通过os.IsNotExist()判断为true,说明文件或文件夹不存在
    • 如果返回的错误类型为其它类型,则不确定是否存在
    package mian
    
    import "os"
    
    func PathIfExists(path string) (bool, error) {
        _, err := os.Stat(path)
        if err == nil {
            // 文件或目录存在
            return true, nil
        }
        if os.IsNotExist(err) {
            // 文件或目录不存在
            return false, nil
        }
    
        return false, err
    }

    2、文件拷贝

    将文本、图片、音频、视频等文件从一个位置拷贝到另一个位置,比如:将 d:/1.jpg拷贝到e:/1.jpg

    其本质就是使用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"
    )
    
    // 接收两个路径参数
    func CopyFile(dstFileName string, srcFileName string) (written int64, err error) {
        // 打开源文件
        srcFile, err := os.Open(srcFileName)
        if err != nil {
            fmt.Printf("open srcFile err %v", err)
            return
        }
        // 延时关闭文件
        defer srcFile.Close()
        // 创建一个读文件的缓冲区
        reader := bufio.NewReader(srcFile)
    
        // 打开目标地址
        dstFile, err := os.OpenFile(dstFileName, os.O_CREATE|os.O_WRONLY, 0666)
    
        if err != nil {
            fmt.Printf("open dstFile err %v", err)
            return
        }
        // 创建一个写文件的缓冲区
        writer := bufio.NewWriter(dstFile)
        // 延时关闭文件
        defer dstFile.Close()
    
        return io.Copy(writer, reader)
    
    }
    
    func main() {
        srcFileName := "d:/1.jpg"
        dstFileName := "e:/1.jpg"
        _, err := CopyFile(dstFileName, srcFileName)
        if err == nil {
            fmt.Println("拷贝完成")
        } else {
            fmt.Printf("拷贝错误 %v", err)
        }
    }
  • 相关阅读:
    python基础27 -----python进程终结篇-----IO模型
    python基础26 -----python进程及协成
    python基础25 -----python高级用法
    python基础24 -----python中的各种锁
    python基础23 -----进程和线程
    Leetcode:5. Longest Palindromic Substring
    Leetcode: 3. Longest Substring Without Repeating Characters
    4. Median of Two Sorted Arrays
    Leetcode:445. Add Two Numbers II
    Leetcode: 43. Multiply Strings
  • 原文地址:https://www.cnblogs.com/shenjianping/p/15833966.html
Copyright © 2020-2023  润新知