目录
一、文件读写
1.读取文件中的数据:
2.写出数据到本地文件:
二、文件复制
1、方法一:io包下的Read()和Write()方法实现
2、方法二:io包下的Copy()方法实现
3、方法三:ioutil包
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
读取数据:
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包,性能都是还不错的。