• Go 文件操作


    文件操作

       作为后端语言,Go通过os包提供了对文件的操作。

       同时,使用bufioioutil也可以进行文件操作,三者均有自身的优劣势结合不同的需求使用不同的包来进行操作,将会让你的事半功倍。

       文件分为普通文件和二进制文件,使用二进制文件时应该按照byte进行读取。

    OpenFile

       在os包中,有一个方法名为OpenFile(),它可以用指定模式来打开一个文件对象,并且会返回一个文件句柄。

    func OpenFile(name string, flag int, perm FileMode) (*File, error) {
    	...
    }
    

      

       name:文件路径

       flag:打开文件的模式

       perm:权限,一个八进制数。r(读)04,w(写)02,x(执行)01。

       下表是flag所支持的模式选项,如果要添加多种模式,使用|进行分割。

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

      

    读取文件

    内容准备

       下面有一个test.txt文件,里面存储了一些歌曲名称,专辑名称,作者名称等信息。

    海阔天空 | Words & Music Final Live | Beyond
    红豆 | 唱游 | 王菲
    我可以抱你吗 | 重拾女人心 | 张惠妹
    味道 | 味道 | 辛晓琪
    独角戏 | 如果云知道 | 许茹芸
    

       打开文件时,可以使用os.Open()方法进行打开,它其实是基于os.OpenFile()的一个封装。

       默认是以只读的方式进行打开。返回一个文件句柄与错误对象。

    func Open(name string) (*File, error) {
    	return OpenFile(name, O_RDONLY, 0)
    }
    

    file.Read

       当获取到文件句柄后,可使用Read()方法对其进行读取。

    func (f *File) Read(b []byte) (n int, err error) {
    	if err := f.checkValid("read"); err != nil {
    		return 0, err
    	}
    	n, e := f.read(b)
    	return n, f.wrapErr("read", e)
    }
    

       这是一个文件句柄的方法,接收一个byte的切片,返回一个interror,其中int是已读取的字节数。

       以下是基本使用:

    package main
    
    import (
    	"fmt"
    	"io"
    	"os"
    )
    
    func readTxt() {
    	// 打开文件,只读方式
    	file, err := os.Open("./file.txt")
    	if err != nil {
    		fmt.Println("打开文件出错:", err)
    		return
    	}
    	defer file.Close() // 关闭文件
    
    	var content []byte
    	var temp = make([]byte, 128) // 创建容纳读取文件的一个变量,byte()类型
    
    	for {
    		// n 以读取的字节数
    		n, err := file.Read(temp) // 使用文件句柄,开始读取。 读取的内容放入temp变量中
    		if err == io.EOF {        // 抛出EOF错误代表文件读取完毕
    			fmt.Println("文件读取完毕")
    			break
    		}
    		if err != nil {
    			fmt.Println("读取文件出错:", err)
    			return
    		}
    		content = append(content, temp[:n]...) // 使用展开语法,将其内容进行展开
    	}
    	fmt.Println(string(content)) // []byte转换为string
    }
    
    func main() {
    	readTxt()
    }
    
    

    bufio

       bufio是一个第三方的包,基于file做了一层封装,支持更多的功能。

       并且它具有缓冲区,能够让读写更加迅速。

       使用NewReader()方法,放入文件句柄,返回一个读取对象,然后再进行指定的方法读取该对象。

       提供的读取方法如下:

    方法描述
    Read 接收一个byte切片,返回以读取字节数
    ReadSlice 返回一个切片,byte类型
    ReadByte 返回byte字符串
    ReadBytes 返回一个切片,byte类型
    ReadRune 返回一个rune字符串
    ReadString 返回一个string的字符串
    ReadLine 以行进行读取,返回一个byte切片,并且会返回一个布尔值判断是否读取完毕

       其实用ReadString就能满足大部分需求了。

    package main
    
    import (
    	"bufio"
    	"fmt"
    	"io"
    	"os"
    )
    
    func readTxt() {
    	// 打开文件,只读方式
    	file, err := os.Open("./file.txt")
    	if err != nil {
    		fmt.Println("打开文件出错:", err)
    		return
    	}
    	defer file.Close() // 关闭文件
    
    	var content string
    	reader := bufio.NewReader(file) // 放入文件句柄,返回读取对象
    	for {
    		line, err := reader.ReadString('
    ') // 以字符 
     作为分割,即每次读取一行
    		if err == io.EOF {
    			fmt.Println("文件读取完毕")
    			break
    		}
    		if err != nil {
    			fmt.Println("读取文件时出错")
    			return
    		}
    		content += line
    	}
    	fmt.Println(content) // 拼接内容
    }
    
    func main() {
    	readTxt()
    }
    
    

    ioutil

       该包位于os/ioutil中,使用其ReadFile()可快速的读取完整个文件。

    package main
    
    import (
    	"fmt"
    	"io/ioutil"
    )
    
    func readTxt() {
    	content, err := ioutil.ReadFile("./file.txt")
    	if err != nil {
    		fmt.Println("读取文件错误:", err)
    		return
    	}
    	fmt.Println(string(content))
    }
    
    func main() {
    	readTxt()
    }
    
    

    写入文件

    write&writeString

       write()接收一个byte切片,返回一个以读取字节数的interror

       writeString()则接收一个string字符串,返回的内容同上。

    package main
    
    import (
    	"fmt"
    	"os"
    )
    
    func writeTxt() {
    	// 创建文件,只写
    	file, err := os.OpenFile("newFile.txt", os.O_CREATE|os.O_WRONLY, 0666)
    	if err != nil {
    		fmt.Println("打开文件时出错", err)
    		return
    	}
    	defer file.Close()
    
    	// 写入文件
    	str := "第一行内容
    "
    	file.Write([]byte(str)) // 写入字节切片
    	file.WriteString("第二行内容
    ")
    }
    
    func main() {
    	writeTxt()
    }
    
    

    bufio.NewWriter

       bufio具有缓冲区,所以读写更加迅速。

       下面是基本使用,其实关于写入对象的写入文件的方法还有很多,这里不再一一例举。

    package main
    
    import (
    	"bufio"
    	"fmt"
    	"os"
    )
    
    func writeTxt() {
    	// 创建文件,只写,清空
    	file, err := os.OpenFile("newFile.txt", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666)
    	if err != nil {
    		fmt.Println("打开文件时出错", err)
    		return
    	}
    	defer file.Close()
    
    	// 写入文件
    	writer := bufio.NewWriter(file) // 放入文件句柄,获得一个写入对象
    	writer.WriteString("一行新数据")
    	writer.Flush() // 缓存刷新到磁盘
    }
    
    func main() {
    	writeTxt()
    }
    
    

    ioutil.WriteFile

       该方法接收一个byte的切片,我们可以直接放入byte切片然后进行写入。

    package main
    
    import (
    	"fmt"
    	"io/ioutil"
    )
    
    func writeTxt() {
    	str := "新数据哦"
    	// 直接写入,清空之前的,会创建新文件
    	err := ioutil.WriteFile("./newFile.txt", []byte(str), 0666)
    	if err != nil {
    		fmt.Println("write file failed, err:", err)
    		return
    	}
    }
    
    func main() {
    	writeTxt()
    }
    
    

    指针偏移

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

       Seeker接口用于包装基本的移位方法。

       Seek方法设定下一次读写的位置:偏移量为offset,校准点由whence确定:0表示相对于文件起始;1表示相对于当前位置;2表示相对于文件结尾。Seek方法返回新的位置以及可能遇到的错误。

       移动到一个绝对偏移量为负数的位置会导致错误。移动到任何偏移量为正数的位置都是合法的,但其下一次I/O操作的具体行为则要看底层的实现。

       以下是一个操纵示例,将最后一行内容进行覆盖修改。

    海阔天空 | Words & Music Final Live | Beyond
    红豆 | 唱游 | 王菲
    我可以抱你吗 | 重拾女人心 | 张惠妹
    味道 | 味道 | 辛晓琪
    独角戏 | 如果云知道 | 许茹芸
    

       操纵过程:

    package main
    
    import (
    	"fmt"
    	"os"
    )
    
    func writeTxt() {
    	// 创建文件,只写
    	file, err := os.OpenFile("file.txt", os.O_WRONLY, 0666)
    	if err != nil {
    		fmt.Println("打开文件时出错", err)
    		return
    	}
    	defer file.Close()
    
    	// 设置指针移动
    	file.Seek(-40, 2)
    
    	// 写入文件
    	str := "全新歌曲 | 全新专辑 | 新歌手
    "
    	file.Write([]byte(str)) // 写入字节切片
    }
    
    func main() {
    	writeTxt()
    }
    
    

       最后结果:

    海阔天空 | Words & Music Final Live | Beyond
    红豆 | 唱游 | 王菲
    我可以抱你吗 | 重拾女人心 | 张惠妹
    味道 | 味道 | 辛晓琪
    全新歌曲 | 全新专辑 | 新歌手  // 进行覆盖
    

    拷贝文件

       借助io.Copy()实现一个拷贝文件函数。

    // CopyFile 拷贝文件函数
    func CopyFile(dstName, srcName string) (written int64, err error) {
    	// 以读方式打开源文件
    	src, err := os.Open(srcName)
    	if err != nil {
    		fmt.Printf("open %s failed, err:%v.
    ", srcName, err)
    		return
    	}
    	defer src.Close()
    	// 以写|创建的方式打开目标文件
    	dst, err := os.OpenFile(dstName, os.O_WRONLY|os.O_CREATE, 0644)
    	if err != nil {
    		fmt.Printf("open %s failed, err:%v.
    ", dstName, err)
    		return
    	}
    	defer dst.Close()
    	return io.Copy(dst, src) //调用io.Copy()拷贝内容
    }
    func main() {
    	_, err := CopyFile("dst.txt", "src.txt")
    	if err != nil {
    		fmt.Println("copy file failed, err:", err)
    		return
    	}
    	fmt.Println("copy done!")
    }
    
  • 相关阅读:
    JQuery EasyUI属性和常见用法
    iOS 设置随意屏幕旋转
    iOS 打印系统字体
    iOS 实时监测网络状态(通过Reachability)
    UITableView上添加按钮,按钮点击效果延迟的解决办法
    ios下通过webservice获取数据
    (转发)InputAccessoryView的使用方法
    (转发)IOS动画中的枚举UIViewAnimationOptions
    (转发)IOS高级开发~Runtime(四)
    (转发)IOS高级开发~Runtime(三)
  • 原文地址:https://www.cnblogs.com/Yunya-Cnblogs/p/13785134.html
Copyright © 2020-2023  润新知