如何在 Go 中操作檔案
go os file

👨💻 簡介
今天快速介紹一下對檔案的操作所使用的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.")
	}
}