網頁

2016年9月11日 星期日

[Go教學] 檔案輸入輸出(基礎)

最近在處理一些資料剛好用到了go的檔案輸入輸出,底下來講一些比較基本的部份吧~

流程以及基本函式:


上面這張圖就是這次要講的4個基本函式,其中最重要的就是OpenFile()以及Close(),以下逐一介紹~



前置處理:
在開始前要先import package os
->  import "os"

package os 的內容可以到官網查詢



開啟及關閉檔案:
首先要有一個觀念
開啟檔案以後一定要關閉,不然檔案會出問題!!

那麼該如何開啟檔案呢?
開啟檔案的時候使用的是os底下的

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

而關閉檔案時的是os底下的

func (f *File) Close() error

具體使用的方法就來個簡單的例子吧~

首先,來看看OpenFile()的部份
OpenFile() :

▶ 第一個參數 name string :
這邊要傳入的是檔案的位置及名稱
在範例中,傳入的是" test.txt " , 也就是在main檔所在資料夾的 test.txt 這個檔案

範例中寫的是相對路徑,相反的則是絕對路徑,兩者都可以使用
  • 相對路徑指的就是 以main檔所在位置來看
    (簡單點說就是: 描述A時說,A在我的左邊)
    • ./dir/test.txt -> 此資料夾內 的 dir資料夾內 的 test.txt
    • ./test.txt or test.txt -> 此資料夾內的test.txt
  • 絕對路徑指的是 準確的位址
    (簡單點說就是: 描述A時說,A在經度XXX緯度YYY的地方)
    • windows: C:\dir\test.txt -> C槽 的 dir內 的 test.txt
    • linux: home/frozenkp/dir/test.txt -> 使用者frozenkp底下 的 dir內 的 test.txt

▶ 第二個參數 flag int :
這邊要傳入的是開啟檔案的模式
範例中 " os.O_RDWR | os.O_CREATE " 意思是 可讀可寫 以及 檔案不存在時創建

由範例中可以看出,當有多個模式時用" | "做間隔

那麼有哪些模式可以用呢??
其實所有的模式都已經作為常數寫在package os裡面了~

呼叫時就像範例一樣 os.O_XXXX | os.O_YYYY | …... 就可以囉~

▶ 第三個參數 perm FileMode :
第三個參數是開啟檔案的模式
範例中使用的是0777,也就是 非資料夾所有人可讀可寫可執行

那這個要怎麼看呢??
這串數字代表的是由二進位構成的 d rwx rwx rwx
(1=true / 0 = false)
  • d -> 是否為資料夾
  • rwx -> 可讀(read) 可寫(write) 執行(execute)
    • 7 (10進位) = 111 (2進位) -> 可讀可寫可執行
    • 4 (10進位) = 100 (2進位) -> 可讀
  • 第一個rwx -> 自己
  • 第二個rwx -> 同組的人
  • 第三個rwx -> 其他人

▶ 第一個回傳變數 *File :
第一個回傳變數是File的指標
在範例中是用 f 儲存

在接下來的使用中,跟這個檔案有關的部份都要使用 f 來操作

▶ 第二個回傳變數 error :
error代表的是是否開啟檔案成功
在範例中是用 err 來儲存 並在後面7~9行判斷是否成功

是不是一定要有這個變數呢??
如果只是自己處理檔案要用的話是可以不要加的喔~
只要改寫成
f , _ := os.OpenFile("test.txt", os.O_RDWR | os.O_CREATE , 0777)
將error省略掉就可以了

如果是比較重要的程式的話還是建議加上去喔,以免導致後面完全都出錯了

Close() :
前面有說過 開啟檔案一定要關閉
關閉的方法就是用剛剛回傳的*File寫下f.Close()

通常會看到兩種寫法
  • 直接在OpenFile()下一行寫下 defer f.Close()
  • 在想關閉的地方寫下  f.Close()

這兩種有什麼差別呢??
第一種就是在這個函式(main或是自己寫的函式) return的時候關閉檔案
第二種是指再出現這行的地方關閉檔案

兩者各有其用需要用到的地方~




處理檔案 :
處理檔案的時候最基本的就是Fscanf()以及Fprintf()了
其實這兩個使用的方法就跟Scanf()以及Peintf()一模一樣喔,只不過多了*File參數 來指定是哪個檔案而已

改寫一下上面的範例試試看

實際執行一次試試看
一開始資料夾內有兩個檔案
2016-09-12 00-03-12 的螢幕擷圖.png

file.go的內容(範例)
2016-09-11 23-59-32 的螢幕擷圖.png

test.txt的內容
2016-09-11 23-59-03 的螢幕擷圖.png

執行 -> 輸出hello
2016-09-12 00-05-15 的螢幕擷圖.png

執行後的test.txt內容 -> 多了holacode
2016-09-12 00-00-09 的螢幕擷圖.png

經過上面的例子應該對使用方法有了初步的了解了
那麼接下來說說Fscanf()以及Fprintf()

首先這兩個函式是包含在package fmt 裡面
因此需要 import "fmt"

接者兩個的完整函式內容
func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error)

func Fscanf(r io.Reader, format string, a ...interface{}) (n int, err error)

使用方法與Printf()以及Scanf()不同的地方就是在參數最前面加上 *File (範例中為f)




學會上面4個函式以後就可以用go作到簡單的檔案輸入輸出囉~
除了基本的這些以外還有很多實用的檔案相關函式包括在os以及fmt裡,以後在進階篇再來詳加介紹吧~

如果對於文章的內容有任何疑問或是我有寫錯的地方都歡迎在底下留言或是直接聯絡我喔OwO

沒有留言:

張貼留言