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字节数据\n", 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字节数据\n", 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(‘\n‘) //字符串读取,每到换行就停止 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\n")) //写入字节切片数据 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\n") ////将数据先写入缓存 } 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\n", 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("\n")) 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)) } }
相关推荐
小科的奋斗 2020-11-16
wfs 2020-10-29
哈嘿Blog 2020-10-26
bearhoopIT之道 2020-11-11
文山羊 2020-11-07
jaminliu0 2020-10-25
railssky 2020-10-25
小科的奋斗 2020-10-24
HELLOBOY 2020-10-23
牧 2020-10-22
狼窝 2020-10-22
ciqingloveless 2020-10-15
专注前端开发 2020-10-12
哈嘿Blog 2020-09-08
linmufeng 2020-09-08
qidiantianxia 2020-09-15
哈嘿Blog 2020-08-16