目录和文件的常用操作

目录的常用操作

package main

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

// IsDir
// @description 检查目录是否存在
// @param dir string 要检查的目录,支持硬盘路径或相对路径
// @return bool 检查结果
func IsDir(dir string) bool {
   stat, err := os.Stat(dir)
   if err != nil {
      return false
   }

   return stat.IsDir()
}

func main() {
   currentPath, _ := filepath.Abs(".") // 获取当前文件目录绝对路径,结尾不带“/”

   // ========== 检查目录是否存在(不存在的例子) ========== //
   dirAbsent := currentPath + "/absent" // 要检查的目录(不存在)
   if IsDir(dirAbsent) {
      fmt.Printf("目录【%+v】存在 \n", dirAbsent)
   } else {
      fmt.Printf("目录【%+v】不存在 \n", dirAbsent) // 目录【D:/go/src/cmd/absent】不存在
   }

   // ========== 检查目录是否存在(存在的例子) ========== //
   dirExist := currentPath + "/exist" // 要检查的目录(存在)
   if IsDir(dirExist) {
      fmt.Printf("目录【%+v】存在 \n", dirExist) // 目录【D:/go/src/cmd/exist】存在
   } else {
      fmt.Printf("目录【%+v】不存在 \n", dirExist)
   }

   // ========== 创建目录(支持多层级) ========== //
   dirUpload := currentPath + "/upload/yyyy/mm/dd" // 要创建的目录
   err := os.MkdirAll(dirUpload, 0755)             // 创建多层级目录,权限为755
   if err != nil {
      fmt.Printf("创建目录【%+v】失败:%+v \n", dirUpload, err.Error())
   } else {
      // 重要说明:目录已存在并不会报错,即err等于nil
      fmt.Printf("创建目录【%+v】成功 \n", dirUpload) // 创建目录【D:/go/src/cmd/upload/yyyy/mm/dd】成功
   }

   // ========== 删除目录(支持多层级,不需要保证目录存在,也不需要保证目录为空) ========== //
   dirRemove := currentPath + "/rm1/rm2/rm3" // 要删除的目录
   err = os.RemoveAll(dirRemove)
   if err != nil {
      fmt.Printf("删除目录【%+v】失败:%+v \n", dirRemove, err.Error())
   } else {
      fmt.Printf("删除目录【%+v】成功 \n", dirRemove) // 删除目录【D:/go/src/cmd/rm1/rm2/rm3】成功
   }
}





文件的常用操作

package main

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

// IsFile
// @description 检查文件是否存在
// @param file string 要检查的文件,支持硬盘路径或相对路径
// @return bool 检查结果
func IsFile(file string) bool {
   stat, err := os.Stat(file)
   if err != nil {
      return false
   }

   // 检查是否为目录
   if stat.IsDir() {
      return false
   }

   return !os.IsNotExist(err)
}

func main() {
   currentPath, _ := filepath.Abs(".") // 获取当前文件目录绝对路径,结尾不带“/”

   // ========== 检查文件是否存在(不存在的例子) ========== //
   fileAbsent := currentPath + "/absent.txt" // 要检查的文件(不存在)
   if IsFile(fileAbsent) {
      fmt.Printf("文件【%+v】存在 \n", fileAbsent)
   } else {
      fmt.Printf("文件【%+v】不存在 \n", fileAbsent)
   }

   // ========== 检查文件是否存在(存在的例子) ========== //
   fileExist := currentPath + "/exist.txt" // 要检查的文件(存在)
   if IsFile(fileExist) {
      fmt.Printf("文件【%+v】存在 \n", fileExist)
   } else {
      fmt.Printf("文件【%+v】不存在 \n", fileExist)
   }

   // ========== 写入文件(使用bufio包,适合用于大文件按行读写) ========== //
   fileBufio := currentPath + "/bufio/test.txt"
   _ = os.MkdirAll(path.Dir(fileBufio), 0755)                                         // 创建文件保存目录
   openFile, err := os.OpenFile(fileBufio, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) // 不存在则创建|只写|尾部追加
   if err != nil {
      fmt.Printf("打开文件【%+v】失败:%+v\n", fileBufio, err.Error())
   } else {
      fmt.Printf("打开文件【%+v】成功\n", fileBufio)
   }

   // 关闭文件(重要提醒:打开和关闭必须成对出现,故最好养成写完打开代码就立即写关闭代码的良好习惯)
   defer func(openFile *os.File) {
      _ = openFile.Close()
   }(openFile)

   // 写入文件(逐行写入)
   bufioWriter := bufio.NewWriter(openFile)
   _, _ = bufioWriter.WriteString("孩儿立志出乡关\n") // 重要提醒:这里只是把字符串放到buffer(缓冲区),还没有真正写入文件
   _, _ = bufioWriter.WriteString("学不成名誓不还\n") // 重要提醒:这里只是把字符串放到buffer(缓冲区),还没有真正写入文件
   _, _ = bufioWriter.WriteString("埋骨何须桑梓地\n") // 重要提醒:这里只是把字符串放到buffer(缓冲区),还没有真正写入文件
   _, _ = bufioWriter.WriteString("人生无处不青山\n") // 重要提醒:这里只是把字符串放到buffer(缓冲区),还没有真正写入文件
   err = bufioWriter.Flush()                   // 重要提醒:执行Flush()才会把内容写入文件
   if err != nil {
      fmt.Printf("写入文件【%+v】失败:%+v\n", fileBufio, err.Error())
   } else {
      fmt.Printf("写入文件【%+v】成功\n", fileBufio)
   }

   // 关闭文件
   err = openFile.Close()
   if err != nil {
      fmt.Printf("关闭文件【%+v】失败:%+v\n", fileBufio, err.Error())
   } else {
      fmt.Printf("关闭文件【%+v】成功\n", fileBufio)
   }

   // 读取文件(逐行读取)
   openFile, err = os.OpenFile(fileBufio, os.O_RDONLY, 0644) // 只读
   if err != nil {
      fmt.Printf("打开文件【%+v】失败:%+v\n", fileBufio, err.Error())
   } else {
      fmt.Printf("打开文件【%+v】成功\n", fileBufio)
   }
   bufioReader := bufio.NewReader(openFile)
   var line string
   i := 0
   for {
      line, err = bufioReader.ReadString('\n')
      if err != nil {
         break // 到达文件末尾或出现错误
      }

      i++
      fmt.Printf("第%d行:%+v", i, line)
   }

   // 关闭文件
   err = openFile.Close()
   if err != nil {
      fmt.Printf("关闭文件【%+v】失败:%+v\n", fileBufio, err.Error())
   } else {
      fmt.Printf("关闭文件【%+v】成功\n", fileBufio)
   }

   // ========== 写入文件(使用os包,适合用于小文件一次读写) ========== //
   fileOs := currentPath + "/os/test.txt"
   _ = os.MkdirAll(path.Dir(fileOs), 0755)                                        // 创建文件保存目录
   openFile, err = os.OpenFile(fileOs, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) // 不存在则创建|只写|尾部追加
   if err != nil {
      fmt.Printf("打开文件【%+v】失败:%+v\n", fileOs, err.Error())
   } else {
      fmt.Printf("打开文件【%+v】成功\n", fileOs)
   }

   _, err = openFile.Write([]byte("秦时明月汉时关\n万里长征人未还\n但使龙城飞将在\n不教胡马度阴山"))
   if err != nil {
      fmt.Printf("写入文件【%+v】失败:%+v\n", fileOs, err.Error())
   } else {
      fmt.Printf("写入文件【%+v】成功\n", fileOs)
   }

   // 关闭文件
   err = openFile.Close()
   if err != nil {
      fmt.Printf("关闭文件【%+v】失败:%+v\n", fileOs, err.Error())
   } else {
      fmt.Printf("关闭文件【%+v】成功\n", fileOs)
   }

   // 读取文件(一次读取)
   var bytes []byte
   bytes, err = os.ReadFile(fileOs)
   if err != nil {
      fmt.Printf("读取文件【%+v】失败:%+v\n", fileOs, err.Error())
   } else {
      fmt.Printf("读取文件【%+v】成功\n", fileOs)
      fmt.Println(string(bytes))
   }

   // ========== 删除文件 ========== //
   fileRemove := currentPath + "/remove.txt"
   err = os.Remove(fileRemove) // 删除文件,若文件不存在会报“remove {文件路径}: The system cannot find the file specified.”
   if err != nil {
      fmt.Printf("删除文件【%+v】失败:%+v\n", fileOs, err.Error())
   } else {
      fmt.Printf("删除文件【%+v】成功\n", fileRemove)
   }

   // ========== 复制文件 ========== //
   fileSrc := currentPath + "/src.txt"     // 源文件
   fileBak := currentPath + "/src.bak.txt" // 目标文件

   // 打开源文件
   var fileSrcOpen *os.File
   fileSrcOpen, err = os.Open(fileSrc)
   if err != nil {
      fmt.Printf("打开文件【%+v】失败:%+v\n", fileSrc, err.Error())
   } else {
      fmt.Printf("打开文件【%+v】成功\n", fileSrc)
   }

   // 打开目标文件
   var fileBakOpen *os.File
   fileBakOpen, err = os.OpenFile(fileBak, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644) // 不存在则创建|只写|打开时清空
   if err != nil {
      fmt.Printf("打开文件【%+v】失败:%+v\n", fileBak, err.Error())
   } else {
      fmt.Printf("打开文件【%+v】成功\n", fileBak)
   }

   // 创建源文件的Reader
   fileSrcReader := bufio.NewReader(fileSrcOpen)

   // 创建目标文件的Writer
   fileBakWriter := bufio.NewWriter(fileBakOpen)

   // 开始复制
   _, err = io.Copy(fileBakWriter, fileSrcReader)
   if err != nil {
      fmt.Printf("复制文件失败:%+v\n" + err.Error())
   } else {
      fmt.Printf("复制文件成功\n")
   }
}

// ========== 概念说明 ========== //
// 流:数据在数据源(文件)和程序(内存)之间经历的路径。
// 输入流:数据从数据源(文件)到程序(内存)的路径,故也叫读文件。
// 输出流:数据从程序(内存)到数据源(文件)的路径,故也叫写文件。

// ========== os.OpenFile()模式可选值 ========== //
// 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  // 如果可能,打开时清空文件

// ========== 总结 ========== //
// 1、逐行读取适用于大文件,一次性读取适用于小文件,尽量根据文件大小分别使用对应的方式。

Copyright © 2024 码农人生. All Rights Reserved