檔案操作


想要進行目錄、檔案等的操作,基本上就是查看 os 套件,可以使用的函式很多,逐一談好像也沒太大意義,基本上若對目錄、檔案以及權限等有所認識,應該查查文件、搜尋一些範例,大致就知道怎麼用吧!

無論如何,輸入輸出中最基本的就是檔案讀寫,至今為止看過,要開啟檔案進行讀取的話,使用的是 os.Open 函式,這會以唯讀方式開啟既有的檔案(否則會有 PathError):

func Open(name string) (*File, error)

如果要指定讀寫方式與權限的話,要使用 os.OpenFile

func OpenFile(name string, flag int, perm FileMode) (*File, error)

flag 可以指定的常數有:

const (
    // 必須指定 O_RDONLY、O_WRONLY 或 O_RDWR
    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  // 檔案開啟時清空文件
)

perm 的話是檔案八進位權限,例如 0777;另外,還有個 os.Create,實現上就是使用 OpenFile 以 0666 的方式建立可讀寫的檔案(清空文件):

func Create(name string) (*File, error) {
    return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
}

OpenOpenFileCreate 都會傳回 *os.File;另外還有個 NewFile,多數情況下用不到,主要是在將檔案描述(File descriptor)以 *os.File 來表示,例如,os.Stdinos.Stdoutos.Stderr,在〈從標準輸入、輸出認識 io〉看過它的使用:

var (
    Stdin  = NewFile(uintptr(syscall.Stdin), "/dev/stdin")
    Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout")
    Stderr = NewFile(uintptr(syscall.Stderr), "/dev/stderr")
)

syscall.Stdinsyscall.Stdoutsyscall.Stderr 分別是標準輸入、輸出、錯誤的檔案描述,這在 syscall 的文件可以看到:

var (
    Stdin  = 0
    Stdout = 1
    Stderr = 2
)

os.File 實作了 io.Readerio.Writer 等行為,因此只要知道〈io.Reader、io.Writer〉,剩下的就是查詢文件,看看有哪些方法可以使用,沒什麼特別需要示範的了,倒是若需要簡單的檔案讀寫,可以看看 ioutil 套件,其中有些簡便的函式:

func NopCloser(r io.Reader) io.ReadCloser
func ReadAll(r io.Reader) ([]byte, error)
func ReadDir(dirname string) ([]os.FileInfo, error)
func ReadFile(filename string) ([]byte, error)
func TempDir(dir, prefix string) (name string, err error)
func TempFile(dir, pattern string) (f *os.File, err error)
func WriteFile(filename string, data []byte, perm os.FileMode) error

ReadFileWriteFile 只要指定檔案名稱等,程式碼上不需要自行建立檔案、緩衝區之類的,這些函式在 ioutil 套件 的文件中,都有範例可以參考。