zoukankan      html  css  js  c++  java
  • Golang文件操作

    文件操作

    • 文件的概念
      文件是数据源(保存数据的地方)的一种,文件最主要的作用就是保存数据.
    • 输入流和输出流
    1. 流:数据在数据源(文件)和程序(内存)之间经历的路径
    2. 输入流:数据从数据源(文件)到程序(内存)的路径
    3. 输出流:数据从程序(内存)到数据源(文件)的路径
    • os.File
      os.File 封装所有文件相关操作,File 是一个结构体
        type File 
        type File struct { 
        // 内含隐藏或非导出字段 
        } 
        //File代表一个打开的文件对象。
    
    • 文件的基本函数
    1. 新建文件
        func Create(filename string) (file *File, err Error)
    

    根据提供的文件名创建新的文件,返回一个文件对象,默认权限是0666的文件,返回的文件对象是可读写的。

        func NewFile(fd uintptr, filename string) *File
    

    根据文件描述符创建相应的文件,返回一个文件对象

    1. 打开文件
        func Open(filename string) (file *File, err error)
    

    Open打开一个文件用于读取。如果操作成功,返回的文件对象的方法可用于读取数据;对应的文件描述符具有O_RDONLY模式。如果出错,错误底层类型是*PathError。
    该方法打开一个名称为filename的文件,但是是只读方式,内部实现其实调用了OpenFile。

        func OpenFile(filename string, flag int, perm uint32) (file *File, err Error)
    

    OpenFile主要用来指定参数(os.O_APPEND|os.O_CREATE|os.O_WRONLY)以及文件权限(0666)来打开文件,如果打开成功返回的文件对象将被用作I/O操作,flag是打开的方式,只读、读写等,perm是权限
    3. 写文件

        func (file *File) Write(b []byte) (n int, err Error)
    

    写入长度为b字节切片到文件f中,返回写入字节号和错误信息。当n不等于len(b)时,将返回非空的err

        func (file *File) WriteAt(b []byte, off int64) (n int, err Error)
    

    在off偏移量出向文件f写入长度为b的字节

        func (file *File) WriteString(s string) (ret int, err Error)
    

    类似于Write方法,但是写入内容是字符串而不是字节切片

        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)
            }
        }
    

    缓冲方式写入

        err = ioutil.WriteFile(filePath, content, 0666)
        if err != nil {
            fmt.Printf("写入文件出错:%v", err)
            return
        }
    

    使用ioutil.WriteFile方式写入文件,是将[]byte内容写入文件,如果content字符串中没有换行符的话,默认就不会有换行符,如果文件不存在将按给出的权限创建文件,否则在写入数据之前清空文件。
    4. 读文件

    func (file *File) Read(b []byte) (n int, err Error)
    

    从文件对象中读取长度为b的字节,返回当前读到的字节数以及错误信息。因此使用该方法需要先初始化一个符合内容大小的空的字节列表。读取到文件的末尾时,该方法返回0,io.EOF

    func (file *File) ReadAt(b []byte, off int64) (n int, err Error)
    

    从文件的off偏移量开始读取长度为b的字节。返回读取到字节数以及错误信息。当读取到的字节数n小于想要读取字节的长度len(b)的时候,该方法将返回非空的error。当读到文件末尾时,err返回io.EOF

        bufio.NewReader(rd io.Reader) *Reader
    
        举例:
        reader := bufio.NewReader(file)
        for {
            line, err := reader.ReadString('
    ') // 读到一个换行符就结束
            if err == io.EOF { // io.EOF表示文件的末尾
                break
            }
        }
    

    缓冲方式读取(默认缓冲区4096字节)

        func ReadFile(filename string) ([]byte, error)
    
        举例:
        content, err := ioutil.ReadFile(filePath)
        if err != nil {
            // log.Fatal(err)
            fmt.Printf("读取文件出错:%v", err)
        }
    

    使用 io/ioutil.ReadFile 方法一次性将文件读取到内存中
    5. 判断文件是否存在

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

    1. 如果返回的错误为 nil,说明文件或文件夹存在;
    2. 如果返回的错误类型使用 os.IsNotExist() 判断为 true,说明文件或文件夹不存在;
      3.如果返回的错误为其他类型,则不确定是否存在。
    1. 关闭文件
        func (f *File) Close() error
    

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

        func Copy(dst Writer, src Reader) (written int64, err error)
    
        举例:
        // 将 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("拷贝文件完成")
        }
    

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

    1. 删除文件
        func Remove(name string) Error
    

    调用该函数就可以删除文件名为name的文件
    9. 断点续传

        package main
        import (
            "os"
            "io"
            "net/http"
            "net/url"
            "strconv"
            )
    
        func main() {
            f, err := os.OpenFile("./chrome_installer.exe", os.O_RDWR|os.O_CREATE, 0666) //O_RDWR|O_CREATE,也就是文件不存在的情况下就建一个空文件,因为windows下还有BUG,如果使用这个O_CREATE,就会直接清空文件,所以windows不用这个标志,你自己事先建立好文件。
            if err != nil {
                panic(err)
            }
            stat, err := f.Stat() //获取文件状态
            if err != nil {
                panic(err)
            }
            f.Seek(stat.Size(), 0) //把文件指针指到文件末,当然你说为何不直接用 O_APPEND 模式打开,没错是可以。我这里只是试验。
            //f.Seek(int64(os.O_APPEND), 0)
            url1 := "http://dl.google.com/chrome/install/696.57/chrome_installer.exe"
            var req http.Request
            req.Method = "GET"
            //req.UserAgent = UA  //客户端信息字符串,不过我加上UserAgent,一直报错,不知道怎么回事,暂时不用它
            req.Close = true
            req.URL, err = url.Parse(url1)
            if err != nil {
                panic(err)
            }
            header := http.Header{}
            header.Set("Range", "bytes="+strconv.FormatInt(stat.Size(), 10)+"-")
            req.Header = header
            resp, err := http.DefaultClient.Do(&req)
            if err != nil {
                panic(err)
            }
            written, err := io.Copy(f, resp.Body)
            if err != nil {
                panic(err)
            }
            println("written: ", written)
        }
    
    • 常用操作
    1. 遍历一个目录
        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())
                }
            }
        }
    
    1. 统计一个文件中含有的英文、数字、空格以及其他字符数量。
        // 定义一个结构体,用于保存统计结果
        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)
        }
    
  • 相关阅读:
    3-百度网盘视频在线倍速播放
    16-算法训练 数字三角形
    【2018ACM/ICPC网络赛】徐州赛区
    【python】collections的使用
    【python】遇到的错误
    【2018ACM/ICPC网络赛】沈阳赛区
    【csp】2018-3
    【python】快速排序
    【csp】2017-12
    【校OJ】选网线
  • 原文地址:https://www.cnblogs.com/KylinBlog/p/13607284.html
Copyright © 2011-2022 走看看