• Go语言文件操作


    获取文件信息

    os.Stat()函数,返回fileInfo和err信息。

    func main() {
        fileInfo, err := os.Stat("xx/test.txt")
        if err != nil {
            fmt.Println("get info err", err)
            return //将函数返回
        }
        //获取文件名
        fmt.Println(fileInfo.Name()) //test.txt
        //获取文件大小
        fmt.Println(fileInfo.Size()) //540
        //是否为目录
        fmt.Println(fileInfo.IsDir()) //false
        //修改时间
        fmt.Println(fileInfo.ModTime()) //2019-08-28 11:28:33.405318773 +0800 CST
        //权限
        fmt.Println(fileInfo.Mode()) //-rw-r--r--
    }
    

    打开和关闭文件

    os.Open()函数能够打开一个文件,返回一个*File和一个err,通过此种方式打开文件是只读的。
    file.close()方法能够关闭文件。

    //打开和关闭文件
    func main()  {
        file,err := os.Open("test.txt")
        if err != nil{
            fmt.Println("打开文件失败",err)
            return
        }
        //文件能打开的情况下,使用defer延迟关闭文件
        defer file.Close()
    }
    

    读取文件

    基本使用

    file.Read()方法可以读取文件,它接收一个字节切片,返回读取的字节数和可能的具体错误,读到文件末尾时会返回0和io.EOF。
    定义:

    func (f *File) Read(b []byte) (n int, err error)
    
    type Reader interface {
        Read(p []byte) (n int, err error)
    }
    

    示例:

    func main() {
        //打开文件
        f,err := os.Open("woceng.txt")
        if err!= nil{
            fmt.Println("文件打开失败",err)
            return
        }
        //关闭文件
        defer f.Close()
        //读取文件
        var geci = make([]byte,256)
        g,err := f.Read(geci)
        if err == io.EOF{
            fmt.Println("文件读取完毕!")
            return
        }
        if err!= nil{
            fmt.Println("文件打开失败",err)
            return
        }
        //只会读取之前切片定义的256字节数据,若文件内容大于256字节,则超出部分无法显示
        fmt.Printf("读取了%d字节数据
    ", g)
        fmt.Println(string(geci[:g])) //将byte转换成string
    }
    

    循环读取

    使用for循环读取。

    var geci = make([]byte,256)
        for {
            g,err := f.Read(geci)
            if err == io.EOF{
                fmt.Println("文件读取完毕!")
                return
            }
            if err!= nil{
                fmt.Println("文件打开失败",err)
                return
            }
            //会全部读取,但是每256字节会进行重新读取,可能会出现乱码
            fmt.Printf("读取了%d字节数据
    ", g)
            fmt.Println(string(geci[:g]))
        }
    

    bufio读取文件

    读取文件中会有个缓冲区,先把内容读到缓冲区,然后统一读取,不过可能会丢数据(内存)。

    func main()  {
        file,err := os.Open("woceng.txt")
        if err != nil{
            fmt.Println("文件读取错误",err)
            return
        }
        defer file.Close()
        // 利用缓冲区从文件读数据
        reader := bufio.NewReader(file)
        for{
            line,err := reader.ReadString('
    ') //字符串读取,每到换行就停止
            if err == io.EOF {
                fmt.Println("文件读完了")
                break
            }
            if err != nil {
                fmt.Println("read file failed, err:", err)
                return
            }
            fmt.Print(line)
        }
    }
    

    ioutil读取整个文件

    ReadFile方法能够读取完整的文件,只需要将文件名作为参数传入。

    // ioutil读取文件
    func readioutil(filename string)  {
        content,err := ioutil.ReadFile(filename)
        if err != nil{
            fmt.Println("文件读取错误",err)
            return
        }
        fmt.Println(string(content))
    }
    

    文件写入

    os.OpenFile()方法实现文件写入相关功能。
    语法:

    func OpenFile(name string, flag int, perm FileMode) (*File, error) {
        ...
    }
    type Writer interface {
        Write(p []byte) (n int, err error)
    }
    

    name:要打开的文件名
    flag:打开文件的模式
    perm:文件权限,一个八进制数

    模式含义
    os.O_WRONLY 只写
    os.O_CREATE 创建文件
    os.O_RDONLY 只读
    os.O_RDWR 读写
    os.O_TRUNC 清空
    os.O_APPEND 追加

    Write和WriteString

    //打开文件支持文件写入
    func main()  {
        file,err := os.OpenFile("test.txt",os.O_CREATE|os.O_APPEND|os.O_WRONLY,0644)
        if err != nil{
            fmt.Println("打开文件失败",err)
            return
        }
        defer file.Close()
        str := "ares"
        file.Write([]byte("666
    ")) //写入字节切片数据
        file.WriteString(str)       //直接写入字符串数据
    }
    

    bufio.NewWriter

    将数据先写入缓存。

    //打开文件支持文件写入
    func main()  {
        file,err := os.OpenFile("test.txt",os.O_CREATE|os.O_APPEND|os.O_WRONLY,0644)
        if err != nil{
            fmt.Println("打开文件失败",err)
            return
        }
        defer file.Close()
        writer := bufio.NewWriter(file)
        for i := 0;i<10;i++{
            writer.WriteString("heoolo
    ")  ////将数据先写入缓存
        }
        writer.Flush()  //将缓存中的内容写入文件
    }
    

    ioutil.WriteFile

    将内容直接写入文件中,避免了打开文件操作。直接覆盖文件内容

    func main()  {
        str := "aresares"
        err := ioutil.WriteFile("test.txt",[]byte(str),0644)
        if err != nil{
            fmt.Println("写文件失败",err)
            return
        }
    }
    

    ioutil.ReadDir实现文件目录遍历

    func listFiles(dirname string, level int) {
        // level用来记录当前递归的层次
        s := "--" //生成空格
        for i := 0; i < level; i++ {
            s = "| " + s
        }
        fileInfos, err := ioutil.ReadDir(dirname)
        if err != nil {
            fmt.Println("err:", err)
        }
        for _, fi := range fileInfos {
            filename := dirname + "/" + fi.Name()
            fmt.Printf("%s%s
    ", s, filename)
            if fi.IsDir() {
                listFiles(filename, level+1)
            }
        }
    
    }
    func main() {
        //目录遍历
        dirname := "/Users/wangxin/Documents"
        listFiles(dirname, 0)
    }
    

    文件复制

    package main
    
    import (
        "fmt"
        "io"
        "io/ioutil"
        "os"
    )
    
    func main() {
        srcFile := "xx/src.txt"
        destFile := "xx/dest1.txt"
        total, err := CopyFile(srcFile, destFile)
        fmt.Println(total, err)
        total1, err := CopyFile1(srcFile, destFile)
        fmt.Println(total1, err)
        total2, err := CopyFile3(srcFile, destFile)
        fmt.Println(total2, err)
    }
    
    //使用io.Copy()方法实现拷贝,返回拷贝的总数量,错误
    func CopyFile(srcFile, destFile string) (int64, error) {
        file1, err := os.Open(srcFile)
        if err != nil {
            return 0, err
        }
        file2, err := os.OpenFile(destFile, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644)
        if err != nil {
            return 0, err
        }
        defer file1.Close()
        defer file2.Close()
        return io.Copy(file2, file1)
    }
    
    //通过io操作实现文件拷贝,返回拷贝的总数量及错误
    func CopyFile1(srcFile, destFile string) (int, error) {
        file1, err := os.Open(srcFile)
        if err != nil {
            return 0, err
        }
        file2, err := os.OpenFile(destFile, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644)
        if err != nil {
            return 0, err
        }
        defer file1.Close()
        defer file2.Close()
        //读写
        str := make([]byte, 100, 100) //拷贝的时间与此处定义的大小有关
        n := -1                       //读取的数据量
        total := 0
        for {
            n, err = file1.Read(str)
            if err == io.EOF || n == 0 {
                fmt.Println("拷贝结束!")
                break
            } else if err != nil {
                fmt.Println("copy err", err)
                return total, err
            }
            total += n
            file2.Write([]byte("
    "))
            file2.Write(str[:n])
        }
        return total, nil
    }
    
    //通过ioutil操作实现文件拷贝,返回拷贝的总数量及错误,不适用大文件
    func CopyFile3(srcFile, destFile string) (int, error) {
        str, err := ioutil.ReadFile(srcFile)
        if err != nil {
            return 0, err
        }
        err = ioutil.WriteFile(destFile, str, 0644)
        if err != nil {
            return 0, err
        }
        return len(str), nil
    }
    

    断点续传

    Seeker接口

    type Seeker interface {
            Seek(offset int64, whence int) (int64, error)
    }
    

    offset:设置偏移量
    whence:

    • 0:seekStart表示相对于文件开始,
    • 1:seekCurrent表示相对于当前偏移量,
    • 2:seek end表示相对于结束。
    func main() {
        file, _ := os.OpenFile("xx/file01/src.txt", os.O_RDWR, 0644)
        defer file.Close()
        //创建一个切片
        str := []byte{0}
        file.Read(str)
        fmt.Println(string(str))   //A
        file.Seek(2, io.SeekStart) //相对文件开始从下标为2的位置开始读取文件
        file.Read(str)
        fmt.Println(string(str))     //C
        file.Seek(3, io.SeekCurrent) //相对于当前位置(下标为2)往后3个偏移量位置读取文件
        file.Read(str)
        fmt.Println(string(str)) //G
        file.Seek(2, io.SeekEnd) //相对于文件末尾,写入文件
        file.WriteString("QWE") //会在文件末尾写入QWE
    }
    

    断点续传实现

    创建一个临时文件,记录已经传递的数据量,当恢复传递的时候,先从临时文件中读取上次已经传递的数据量,然后通过Seek()方法,设置到该读和该写的位置,再继续传递数据。

    //定义一个错误处理函数
    func HandleErr(err error) {
        if err != nil {
            fmt.Println(err)
        }
    }
    func main() {
        srcFile := "xx/src.txt"
        destFile := "xx/src1.txt"
        //destFile := srcFile[strings.LastIndex(srcFile, "/")+1:] + "dest.txt" //获取源文件名
        tempFile := destFile + "tmp.txt" //临时文件
        //fmt.Println(srcFile)
        //fmt.Println(destFile)
        //fmt.Println(tempFile)
        file1, err := os.Open(srcFile)
        HandleErr(err)
        file2, err := os.OpenFile(destFile, os.O_CREATE|os.O_WRONLY, 0644)
        HandleErr(err)
        file3, err := os.OpenFile(tempFile, os.O_CREATE|os.O_RDWR, 0644)
        HandleErr(err)
        defer file1.Close()
        defer file2.Close()
        //读取临时文件中的数据
        file3.Seek(0, io.SeekStart)
        //创建切片存储临时文件数据
        bs := make([]byte, 100, 100)
        n1, err := file3.Read(bs)
        HandleErr(err)
        fmt.Println(n1)
        countStr := string(bs[:n1])                     //获取临时文件的数据
        couunt, _ := strconv.ParseInt(countStr, 10, 64) //将数据转为10进制64位数据
        fmt.Println(couunt)
        //设置读写的偏移量
        file1.Seek(couunt, io.SeekStart)
        file2.Seek(couunt, io.SeekStart)
        data := make([]byte, 1024, 1024)
        n2 := -1             //读的数据量
        n3 := -1             //写的数据量
        total := int(couunt) //读取总量
        //读取数据
        for {
            n2, err = file1.Read(data)
            if err == io.EOF || n2 == 0 {
                fmt.Println("复制完毕、、")
                file3.Close()
                //删除临时文件
                os.Remove(tempFile)
                break
            }
            //将数据写入目标文件
            n3, _ = file2.Write(data[:n2])
            total += n3
            //将复制总量,存储到临时文件中
            file3.Seek(0, io.SeekStart)
            file3.WriteString(strconv.Itoa(total))
        }
    }
  • 相关阅读:
    在CentOS 8上安装Jitsi Meet
    centos8 安装docker
    [git]error: pack-objects died of signal
    Andorid 11调用系统裁剪
    XCode修改工程名(完美版)
    java分割后台日志
    五分钟搞定WebRTC视频录制
    一分钟教你构建属于你的视频会议SDK
    史上最全的WebRTC服务器技术选型分析
    数据库设计之思考
  • 原文地址:https://www.cnblogs.com/show58/p/12421955.html
Copyright © 2020-2023  润新知