👨‍💻 簡介

今天快速介紹一下對檔案的操作所使用的package os,包括檔案和資料夾操作等。

檔案和資料夾操作

os package 可以執行各種檔案和資料夾操作,如建立、讀取、寫入、刪除檔案,以及取得資料夾內容等。

建立相關操作

  • os.Create:建立一個新檔案。
  • os.Mkdir:建立一個新資料夾。
  • os.MkdirAll:建立資料夾,包括必要的父層資料夾。

語法如下:

func os.Create(name string) (*os.File, error)
func os.Mkdir(name string, perm fs.FileMode) error
func os.MkdirAll(path string, perm fs.FileMode) error
package main

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

func main() {

	// 建立資料夾,指定權限為755
	err := os.Mkdir("mydir", 0755)
	if err != nil {
		fmt.Println("Error creating directory:", err)
	} else {
		fmt.Println("Directory created successfully.")
	}

	// 建立一個新檔案並寫入內容
	file, err := os.Create("example.txt")
	if err != nil {
		fmt.Println(err)
		return
	}
	defer file.Close()
	file.WriteString("Hello, World!")
}

讀寫相關操作

  • os.Open:打開一個檔案進行讀取操作。
  • os.OpenFile:打開一個檔案,可以指定更多的選項,如讀寫模式和權限。
  • os.Getwd:取得當前路徑
  • os.Stat:取得檔案或資料夾訊息。
  • os.IsNotExist:檢查檔案或資料夾是否存在。
  • os.Rename:重命名檔案或資料夾

語法如下:

func os.Open(name string) (*os.File, error)
func OpenFile(name string, flag int, perm FileMode) (*File, error)
func os.Getwd() (dir string, err error)
func os.Stat(name string) (fs.FileInfo, error)
func os.IsNotExist(err error) bool

OpenFile的細項介紹:

第一個參數為檔名,第二個為要對檔案使用的選項,第三個則為檔案權限的設定。

常見的選項有以下幾種:

  • O_RDONLY:以只讀模式打開檔案,不允許寫入。
  • O_WRONLY:以只寫模式打開檔案,不允許讀取。
  • O_APPEND:以附加模式打開檔案,新內容將附加到檔案末尾。
  • O_TRUNC:如果檔案存在,則清空檔案內容。
  • O_EXCL:與 O_CREATE 一起使用時,只有在檔案不存在時才建立檔案,用於防止檔案競爭。
package main

import (
	"fmt"
	"os"
)

func main() {
	// 打開檔案並讀取內容
	readFile, err := os.Open("example.txt")
	if err != nil {
		fmt.Println(err)
		return
	}
	defer readFile.Close()

	// 打開一個檔案以進行讀寫操作
	file, err := os.OpenFile("example.txt", os.O_RDWR|os.O_CREATE, 0755)
	if err != nil {
		fmt.Println("Error opening file:", err)
		return
	}
	defer file.Close()

	// 取得當前工作資料夾
	wd, err := os.Getwd()
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	fmt.Println("Current Working Directory:", wd)
}

這邊另外介紹一下Stat,

Stat會回傳一個FileInfo的interface

type FileInfo interface {
	Name() string       // base name of the file
	Size() int64        // length in bytes for regular files; system-dependent for others
	Mode() FileMode     // file mode bits
	ModTime() time.Time // modification time
	IsDir() bool        // abbreviation for Mode().IsDir()
	Sys() any           // underlying data source (can return nil)
}
package main

import (
	"fmt"
	"os"
)

func main() {

	fileInfo, err := os.Stat("example.txt")
	if err == nil {
		fmt.Println("File exists.")
	} else if os.IsNotExist(err) {
		fmt.Println("File does not exist.")
	} else {
		fmt.Println("Error:", err)
	}
	
	// 取得檔案資訊
	fmt.Println(fileInfo.Name())   
	fmt.Println(fileInfo.IsDir())  
	fmt.Println(fileInfo.Size())    
	fmt.Println(fileInfo.ModTime()) 
	fmt.Println(fileInfo.Mode())   

}

要寫入檔案則需要先取得os.File物件,可透過Openfile取得。 先來看一下WriteString語法

func (*os.File).WriteString(s string) (n int, err error)

其中s為要寫入的內容,n為寫入的字節數

package main

import (
	"fmt"
	"os"
)

func main() {
	// 打開一個檔案以進行寫入操作
	file, err := os.OpenFile("example.txt", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
	if err != nil {
		fmt.Println("Error opening file:", err)
		return
	}
	defer file.Close()

	// 寫入內容到檔案
	_, err = file.WriteString("Hello, Appended Content!")
	if err != nil {
		fmt.Println("Error writing to file:", err)
		return
	}

	fmt.Println("File opened and written in append mode successfully.")
}

最後介紹一下Rename,語法如下:

func os.Rename(oldpath string, newpath string) error
package main

import (
	"fmt"
	"os"
)

func main() {
	// 重命名檔案
	err := os.Rename("oldfile.txt", "newfile.txt")
	if err != nil {
		fmt.Println("Error:", err)
		return
	}

	// 重命名資料夾
	err = os.Rename("olddir", "newdir")
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
}

刪除相關操作

  • os.Remove:刪除檔案和資料夾,如果資料夾不為空會報錯。
  • os.RemoveAll:刪除檔案和資料夾。

兩種使用方法都很類似,語法為

func os.Remove(name string) error
func os.RemoveAll(path string) error
package main

import (
	"fmt"
	"os"
)

func main() {

	file, err := os.Create("example.txt")
	if err != nil {
		fmt.Println(err)
		return
	}
	defer file.Close()

	err := os.Remove("example.txt")
	if err != nil {
		fmt.Println("Error deleting file:", err)
	} else {
		fmt.Println("File deleted successfully.")
	}

	testDir := "d1/d2/d3"
	// Create Recursive dir
	err := os.MkdirAll(testDir, os.ModePerm)
	if err != nil {
		fmt.Println("Error creating directory:", err)
	}
	// 使用 os.RemoveAll() 刪除資料夾
	err = os.RemoveAll("d1")
	// err = os.Remove("d1")  // 因資料夾不為空,因此會噴directory not empty錯誤
	if err != nil {
		fmt.Println("Error deleting directory:", err)
	} else {
		fmt.Println("Directory deleted successfully.")
	}
}

📚 參考資料