Golang 文件操作 - 下篇

目錄

1、文件的重命名和刪除

os包自帶重命名和刪除的方法

package main

import "os"

func main()  {
 os.Rename("user.log""user.v2.log")
 os.Remove("user.txt")
}

2、文件路徑的獲取

文件路徑操作包括對文件路徑、文件名等

package main

import (
 "fmt"
 "os"
 "path/filepath"
)

func main() {
 fmt.Println(filepath.Abs("."))  // 獲取當前路徑,和Getwd相同
 fmt.Println(os.Args)
 fmt.Println(filepath.Abs(os.Args[0]))  // 當前程序運行的絕對路徑
 path, _ := filepath.Abs(os.Args[0])

 fmt.Println(filepath.Base("c:/test/a.txt"))  // basename 文件名 a.txt
 fmt.Println(filepath.Base("c:/test/xxxx/"))  // basename 目錄名 xxxx
 fmt.Println(filepath.Base(path))

 fmt.Println(filepath.Dir("c:/test/a.txt"))  // 獲取目錄名 c:/test
 fmt.Println(filepath.Dir("c:/test/xxxx/"))  // 獲取目錄名 c:/test/xxxx
 fmt.Println(filepath.Dir(path))

 fmt.Println(filepath.Ext("c:/test/a.txt"))  // 獲取擴展名 .txt
 fmt.Println(filepath.Ext("c:/test/xxxx/a"))  // 空
 fmt.Println(filepath.Ext(path))       // 空

 dirPath := filepath.Dir(path)
 iniPath := dirPath + "/conf/ip.ini"
 fmt.Println(iniPath)  // 拼接配置文件路徑

 fmt.Println(filepath.Join(dirPath, "conf""ip.ini"))  // 組裝配置文件路徑
 fmt.Println(filepath.Glob("./[ab]*/*.go"))   // 找文件 找當前路徑下目錄名包含ab,以go文件結尾
 filepath.Walk(".", func(path string, fileInfo os.FileInfo, err error) error {  // 遍歷路徑下所有子孫目錄
  fmt.Println(path, fileInfo.Name())
  return nil
 })
}

3、判斷文件是否存在

主要是通過os包的open方法打開文件,並接收返回的錯誤信息,給os包的IsNotExist函數判斷,返回一個布爾值

package main

import (
 "fmt"
 "os"
)

func main()  {
 file, err := os.Open("xxx")
 if err != nil {
  if os.IsNotExist(err){
   fmt.Println("文件不存在")
  }
 } else {
  file.Close()
 }
}

4、獲取文件的信息

獲取文件信息及文件夾的子文件信息lstat:如果是超鏈接,獲取的是超鏈接的信息stat:如果是超鏈接,獲取的是目標文件的信息

package main

import (
 "fmt"
 "os"
)

func main()  {
 for _, path := range []string{"user.txt""reader.go""aaa"} {  // 循環文件名
  fileInfo, err := os.Stat(path)
  if err != nil {
   if os.IsNotExist(err){
    fmt.Println("文件不存在")
   }
  } else {
   fmt.Println(fileInfo.Name(), fileInfo.IsDir(), fileInfo.Size(), fileInfo.ModTime())
   //文件名 是否是目錄 大小 修改時間
   //user.txt false 12 2021-08-30 16:20:54.853211783 +0800 CST
   //reader.go false 387 2021-08-30 15:57:06.860696025 +0800 CST
   if fileInfo.IsDir() {  // 獲取目錄下的子目錄及文件
    dirfile, err := os.Open(path)
    if err == nil {
     defer dirfile.Close()
     //childrens, _ := dirfile.Readdir(-1)  // 獲取所有的子目錄
     //for _, children := range childrens {
     // fmt.Println(children.Name(), children.IsDir(), children.Size(), children.ModTime())
     //}
     names, _ := dirfile.Readdirnames(-1)
     for _, name := range names {
      fmt.Println(name)
     }
    }
   }
  }
 }
}

5、拷貝文件

copyfile功能的實現,主要藉助於golang自帶的命令行解析工具flag(這個在後面的文章中會專門介紹),通過bufio讀取並寫入文件

package main

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

func copyfile(src, dest string) {
 srcfile, err := os.Open(src)
 if err != nil {
  fmt.Println(err)
 } else {
  defer srcfile.Close()
  destfile, err := os.Create(dest)
  if err != nil {
   fmt.Println(err)
  } else {
   defer destfile.Close()
   reader := bufio.NewReader(srcfile)
   writer := bufio.NewWriter(destfile)
   bytes := make([]byte, 1024*1024*10)  // 緩衝區大小
   for {
    n, err := reader.Read(bytes)
    if err != nil {
     if err != io.EOF {
      fmt.Println(err)
     }
     break
    }
    writer.Write(bytes[:n])
    //destfile.Write(bytes[:n])
    writer.Flush()
   }
  }
 }
}

func main() {
 src := flag.String("s""""src file")
 dest := flag.String("d""""dest file")
 help := flag.Bool("h", false, "help")

 flag.Usage = func() {
  fmt.Println(`
Usage: copyfile -s srcfile -d destfile
Options:
  `)
  flag.PrintDefaults()
 }

 flag.Parse()
 if *help || *src == "" || *dest == "" {
  flag.Usage()
 } else {
  copyfile(*src, *dest)
 }
}

支持遞歸拷貝目錄及目錄下的文件

package main

import (
 "bufio"
 "flag"
 "fmt"
 "io"
 "io/ioutil"
 "os"
 "path/filepath"
)

func copyFile(src, dest string) {
 srcFile, err := os.Open(src)
 if err != nil {
  fmt.Println(err)
 } else {
  defer srcFile.Close()
  destFile, err := os.Create(dest)
  if err != nil {
   fmt.Println(err)
  } else {
   defer destFile.Close()
   reader := bufio.NewReader(srcFile)
   writer := bufio.NewWriter(destFile)
   bytes := make([]byte, 1024*1024*10)  // 緩衝區大小
   for {
    n, err := reader.Read(bytes)
    if err != nil {
     if err != io.EOF {
      fmt.Println(err)
     }
     break
    }
    writer.Write(bytes[:n])
    //destfile.Write(bytes[:n])
    writer.Flush()
   }
  }
 }
}

func copyDir(src, dst string) {
 files, err := ioutil.ReadDir(src)
 if err == nil {
  os.Mkdir(dst, os.ModePerm)  // 目標路徑不存在先創建目錄
  for _, file := range files {
   if file.IsDir() {  // 目錄 遞歸調用
    copyDir(filepath.Join(src, file.Name()), filepath.Join(dst, file.Name()))
   } else {  // 文件 拷貝文件
    copyFile(filepath.Join(src, file.Name()), filepath.Join(dst, file.Name()))
   }
  }
 }
}

func main() {
 src := flag.String("s""""src file")
 dest := flag.String("d""""dest file")
 help := flag.Bool("h", false, "help")

 flag.Usage = func() {
  fmt.Println(`
Usage: copyfile -s srcfile -d destfile
Options:
  `)
  flag.PrintDefaults()
 }

 flag.Parse()
 if *help || *src == "" || *dest == "" {
  flag.Usage()
 } else {
  // src是否存在 不存在則退出
  // src 文件 copyfile
  // dst 判斷 存在 退出

  // src 目錄 copydir
  // dst 判斷 不存在 copy
  // dst 存在 目錄
  // dst 存在 不是目錄 退出
  if _, err := os.Stat(*dest); err == nil {
   fmt.Println("目的文件已存在")
   return
  } else {
   if !os.IsNotExist(err) {
    fmt.Println("目的文件獲取錯誤", err)
   }
  }
  if info, err := os.Stat(*src); err != nil {
   if os.IsNotExist(err) {
    fmt.Println("源文件不存在")
   } else {
    fmt.Println("源文件獲取錯誤: ", err)
   }
  } else {
   if info.IsDir() {
    copyDir(*src, *dest)
   } else {
    copyFile(*src, *dest)
   }
  }
 }
}

6、目錄操作

目錄的創建、刪除和重命名

package main

import "os"

func main()  {
 os.Mkdir("test01", 0644)
 os.Rename("test01""test02")
 os.Remove("test02")
}

創建子目錄,當父目錄不存在的時候需要使用mkdirAll,並設置權限(創建目錄除了給定的權限還要加上系統的UmaskGo也是如實遵循這種約定,Umask是權限的補碼,用於設置創建文件和文件夾默認權限的)

package main

import (
 "os"
 "syscall"
)

func main()  {
 //os.Mkdir("test01", 0644)  // 如果目錄存在會報錯
 //os.Rename("test01""test02")
 //os.Remove("test02")

 //err := os.Mkdir("test01/xxx", 0644)
 //fmt.Println(err)  // mkdir test01/xxx: no such file or directory
 mask := syscall.Umask(0)    // 改爲 0000 八進制
 defer syscall.Umask(mask)   // 改爲原來的 umask
 err := os.MkdirAll("test01/test/", 0777)  // MkdirAll創建
 if err != nil {
  panic(err)
 }
 os.RemoveAll("test01")
}

7、常見目錄

package main

import (
 "fmt"
 "os"
)

func main() {
 fmt.Println(os.TempDir())  // 臨時目錄
 fmt.Println(os.UserCacheDir())  // 用戶緩存目錄
 fmt.Println(os.UserHomeDir())  // 用戶家目錄
 fmt.Println(os.Getwd())  // 當前絕對目錄
}

See you ~

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/6dkmufKCBm2AzoO7aLa0AQ