目录
file类是在os包中的,封装了底层的文件描述符和相关信息,同时封装了Read和Write的实现。
- func (f *File) Read(b []byte) (n int, err error)
- //Read方法从f中读取最多len(b)字节数据并写入b。它返回读取的字节数和可能遇到的任何错误。文件终止标志是读取0个字节且返回值err为io.EOF。
-
- func (f *File) ReadAt(b []byte, off int64) (n int, err error)
- //ReadAt从指定的位置(相对于文件开始位置)读取len(b)字节数据并写入b。它返回读取的字节数和可能遇到的任何错误。当n
-
- func (f *File) Write(b []byte) (n int, err error)
- //Write向文件中写入len(b)字节数据。它返回写入的字节数和可能遇到的任何错误。如果返回值n!=len(b),本方法会返回一个非nil的错误。
-
- func (f *File) WriteString(s string) (ret int, err error)
- //WriteString类似Write,但接受一个字符串参数。
-
- func (f *File) WriteAt(b []byte, off int64) (n int, err error)
- //WriteAt在指定的位置(相对于文件开始位置)写入len(b)字节数据。它返回写入的字节数和可能遇到的任何错误。如果返回值n!=len(b),本方法会返回一个非nil的错误。
-
- func (f *File) Seek(offset int64, whence int) (ret int64, err error)
- //Seek设置下一次读/写的位置。offset为相对偏移量,而whence决定相对位置:0为相对文件开头,1为相对当前位置,2为相对文件结尾。它返回新的偏移量(相对开头)和可能的错误。
-
- func (f *File) Sync() (err error)
- //Sync递交文件的当前内容进行稳定的存储。一般来说,这表示将文件系统的最近写入的数据在内存中的拷贝刷新到硬盘中稳定保存。
读取数据:
Reader接口:
Read(p []byte)(n int, error)
示例代码:
- package main
-
- import (
- "fmt"
- "io"
- "os"
- )
-
- func main() {
- //读取本地aa.txt文件中的数据
- //step1:打开文件
- fileName := "abcd.txt"
- file,err := os.Open(fileName)
- if err != nil{
- fmt.Println("err:",err)
- return
- }
- //step3:关闭文件
- defer file.Close()
-
- //step2:读取数据
- bs := make([]byte,4,4)
- /*
- //第一次读取
- n,err :=file.Read(bs)
- fmt.Println(err) //
- fmt.Println(n) //4
- fmt.Println(bs) //[97 98 99 100]
- fmt.Println(string(bs)) //abcd
- //第二次读取
- n,err = file.Read(bs)
- fmt.Println(err)//
- fmt.Println(n)//4
- fmt.Println(bs) //[101 102 103 104]
- fmt.Println(string(bs)) //efgh
- //第三次读取
- n,err = file.Read(bs)
- fmt.Println(err) //
- fmt.Println(n) //2
- fmt.Println(bs) //[105 106 103 104]
- fmt.Println(string(bs)) //ijgh
- //第四次读取
- n,err = file.Read(bs)
- fmt.Println(err) //EOF
- fmt.Println(n) //0
- */
- n := -1
- for{
- n,err = file.Read(bs)
- if n == 0 || err == io.EOF{
- fmt.Println("读取到了文件的末尾,结束读取操作。。")
- break
- }
- fmt.Println(string(bs[:n]))
- }
- }
- package main
-
- import (
- "os"
- "fmt"
- "log"
- )
-
- func main() {
- /*
- 写出数据:
- */
-
- fileName := "/Users/ruby/Documents/pro/a/ab.txt"
- //step1:打开文件
- //step2:写出数据
- //step3:关闭文件
- //file,err := os.Open(fileName)
- file,err := os.OpenFile(fileName,os.O_CREATE|os.O_WRONLY|os.O_APPEND,os.ModePerm)
- if err != nil{
- fmt.Println(err)
- return
- }
- defer file.Close()
-
- //写出数据
- //bs :=[]byte{65,66,67,68,69,70}//A,B,C,D,E,F
- bs :=[] byte{97,98,99,100} //a,b,c,d
- //n,err := file.Write(bs)
- n,err := file.Write(bs[:2])
- fmt.Println(n)
- HandleErr(err)
- file.WriteString("\n")
-
- //直接写出字符串
- n,err = file.WriteString("HelloWorld")
- fmt.Println(n)
- HandleErr(err)
-
- file.WriteString("\n")
- n,err =file.Write([]byte("today"))
- fmt.Println(n)
- HandleErr(err)
-
- }
-
- func HandleErr(err error){
- if err != nil{
- log.Fatal(err)
- }
- }
在io包中主要是操作流的一些方法,今天主要学习一下copy。就是把一个文件复制到另一个目录下。它的原理就是通过程序,从源文件读取文件中的数据,在写出到目标文件里。
我们可以通过io包下的Read()和Write()方法,边读边写,就能够实现文件的复制。这个方法是按块读取文件,块的大小也会影响到程序的性能。
- /*
- 该函数的功能:实现文件的拷贝,返回值是拷贝的总数量(字节),错误
- */
- 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_CREATE,os.ModePerm)
- if err !=nil{
- return 0,err
- }
- defer file1.Close()
- defer file2.Close()
- //拷贝数据
- bs := make([]byte,1024,1024)
- n :=-1//读取的数据量
- total := 0
- for {
- n,err = file1.Read(bs)
- if err == io.EOF || n == 0{
- fmt.Println("拷贝完毕。。")
- break
- }else if err !=nil{
- fmt.Println("报错了。。。")
- return total,err
- }
- total += n
- file2.Write(bs[:n])
- }
- return total,nil
-
- }
我们也可以直接使用io包下的Copy()方法。
示例代码如下:
- func copyFile2(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_CREATE,os.ModePerm)
- if err !=nil{
- return 0,err
- }
- defer file1.Close()
- defer file2.Close()
-
- return io.Copy(file2,file1)
- }
使用ioutil包中的 ioutil.WriteFile()和 ioutil.ReadFile(),但由于使用一次性读取文件,再一次性写入文件的方式,所以该方法不适用于大文件,容易内存溢出。
示例代码:
- func copyFile3(srcFile, destFile string)(int,error){
- input, err := ioutil.ReadFile(srcFile)
- if err != nil {
- fmt.Println(err)
- return 0,err
- }
-
- err = ioutil.WriteFile(destFile, input, 0644)
- if err != nil {
- fmt.Println("操作失败:", destFile)
- fmt.Println(err)
- return 0,err
- }
-
- return len(input),nil
- }
这3种方式,在性能上,不管是还是io.Copy()还是ioutil包,性能都是还不错的。