Go 文件操作

#### Go 文件操作
文件在程序是以流的形式操作的, 在Python,JAVA,Go ... 都一样;
流: 数据在数据源和程序之间经过的路径
输入流: 数据从数据源到程序的路径
输出流: 数据从程序到数据源的路径
下面来学习一下在Go中如何操作文件;
os.File 封装了所有文件相关的操作,File 是一个结构体,有很多方法

   
##### 打开和关闭文件
package main

import (
   "fmt"
   "os"
)

func main(){
   // 打开文件
   // 默认返回两个值
   // 第一个为file 对象,也可称为file 指针
   // 第二个为错误信息,如果有错误,则err != nil
   file,err := os.Open("./test.txt")
   if err != nil {
      fmt.Println("open file error")
      fmt.Println(err)
      return
   }
   // 正常情况下打开文件后,file 实际上是一个指针,类型为*File
   fmt.Printf("file=%v",file)
   // 正常操作完文件后需要手动关闭文件,避免内存泄漏
   err = file.Close()
   if err != nil {
      fmt.Println("close file error")
   }
}

  


##### 读取文件
package main

import (
   "bufio"
   "fmt"
   "io"
   "io/ioutil"
   "os"
)

func main(){
   // 打开文件
   // 默认返回两个值
   // 第一个为file 对象,也可称为file 指针
   // 第二个为错误信息,如果有错误,则err != nil
   file,err := os.Open("./test.txt")
   if err != nil {
      fmt.Println("open file error")
      fmt.Println(err)
      return
   }
   // 正常情况下打开文件后,file 实际上是一个指针,类型为*File
   fmt.Printf("file=%v\n",file)
   // 正常操作完文件后需要手动关闭文件,避免内存泄漏
   defer file.Close()
   // 第一种方式: 带缓冲方式读取文件
   reader := bufio.NewReader(file)
   //var content []byte
   for {
      //1. 一行一行读取
      str,err := reader.ReadString('\n')
      //2. 带缓冲读取
      //buf := make([]byte,1024)
      //n,err := reader.Read(buf)
      //content = append(content,buf[:n]...)
      if err == io.EOF {
         break
      }
      fmt.Print(str)
   }
   fmt.Println("file read end...")
   // 第二种方式: 一次性读取所有文件内容
   // 适用于文件内容不大的情况
   // ioutil.ReadFile 返回两个值,一个是读取到的内容字节切片,
   // 一个是返回的错误信息
   content,err := ioutil.ReadFile("test.txt")
   if err != nil {
      fmt.Println(err)
      return
   }
   fmt.Println(string(content))
   // ioutil.ReadFile 不需要显示的close 文件, open 和 close 方法被封装在ReadFile 内部
}

  


##### 写文件
关于打开文件指定选择,可以自行测试,特别是O_APPEND,O_TRUNC 使用较多;
package main

import (
   "bufio"
   "fmt"
   "os"
)

func main(){
   // os.OpenFile 是一个更为通用的函数,它需要三个参数,
   // 1. 文件路径
   // 2. 指定选项,以下选项可组合使用
      //O_RDONLY int = syscall.O_RDONLY // 以只读方式打开文件
      //O_WRONLY int = syscall.O_WRONLY // 以只写方式打开文件
      //O_RDWR   int = syscall.O_RDWR   // 以读写模式打开文件
      //O_APPEND int = syscall.O_APPEND // 以写操作时将内容追加到文件末尾
      //O_CREATE int = syscall.O_CREAT  // 如果文件不存在,则创建新的文件
      //O_EXCL   int = syscall.O_EXCL   // 和O_CREATE 一起使用,文件必须不存在
      //O_SYNC   int = syscall.O_SYNC   // 打开文件以同步I/O
      //O_TRUNC  int = syscall.O_TRUNC  // 如果可能,打开文件时清空文件
   // 3. 文件模式
   // linux r=4,w=2,x=1
   file,err := os.OpenFile("./abc.txt",os.O_WRONLY| os.O_CREATE,0666)
   if err != nil {
      fmt.Println("file open error")
      return
   }
   defer file.Close()
   writer := bufio.NewWriter(file)
   for i := 0;i<5;i++{
      writer.WriteString("hello,golang\n")
   }
   // bufio.NewWriter 是带缓冲的写,如果不调用Flush 方法, 那么数据不会写入文件
   writer.Flush()
}

  


##### 判断文件是否存在
Go 中判断文件或文件夹是否存在的方法为使用os.Stat() 函数返回的错误值进行判断
1. 如果返回的错误为nil ,说明文件或文件夹存在
2. 如果返回的错误类型使用os.IsNotExist() 判断为true, 说明文件或文件夹不存在
3. 如果返回的错误为其它类型, 则不确定是否存在
func PathExists(path string)(bool,error) {
   _,err := os.Stat(path)
   if err != nil {
      if os.IsNotExist(err) {
         return false,nil
      }
      return false,err
   }
   return true,nil
}

  


##### 文件复制
package main

import (
   "bufio"
   "fmt"
   "io"
   "os"
)

func copyFile(srcFileName,destFileName string)(int64,error){
   srcFile,err := os.Open(srcFileName)
   if err != nil {
      return 0,err
   }
   defer srcFile.Close()
   reader := bufio.NewReader(srcFile)
   destFile,err := os.OpenFile(destFileName,os.O_CREATE|os.O_WRONLY,0666)
   if err != nil {
      return 0,err
   }
   writer := bufio.NewWriter(destFile)
   defer destFile.Close()
   n,err := io.Copy(writer,reader)
   // 如果不调用 Flush 将会出现目标文件没有内容
   writer.Flush()
   return n,err
}
func main(){
   _,err := copyFile("./a.jpg","./b.jpg")
   if err != nil {
      fmt.Println("copy file error")
      fmt.Println(err)
      return
   }
   fmt.Println("file copy finish")
}

  

最新文章会在个人微信公众号上同步更新,欢迎关注,大家一同交流学习 

posted @ 2019-09-20 10:02  mail_maomao  阅读(1313)  评论(0编辑  收藏  举报