Fi

File 在 Elixir

2 個練習

關於 File

處理檔案用的函式由 File模組提供。

要讀取整個檔案,請使用 File.read/1。要寫入檔案,請使用 File.write/2。

這個模組也提供複製、刪除、重新命名等檔案相關函式。它們的名稱和 UNIX 中對應的功能類似,例如:

上述 File模組中的所有函式都有一個 !版本,這個版本會拋出錯誤,而不是回傳錯誤元組(例如 File.read!/1)。如果你不打算處理檔案不存在或權限不足這類錯誤,就使用這個版本。

File.read("does_not_exist")
# => {:error, :enoent}

File.read!("does_not_exist")
# => ** (File.Error) could not read file "does_not_exist": no such file or directory
#        (elixir 1.10.4) lib/file.ex:353: File.read!/1

檔案與行程

每次用 File.write/2寫入檔案時,都會開啟一個檔案描述子,並產生一個新的 Elixir 行程。基於這個原因,應該避免在迴圈中用 File.write/2寫入檔案。

取而代之的是,可以用 File.open/2開啟檔案。File.open/2的第二個引數是一串模式,讓你可以指定要以讀取還是寫入的方式開啟檔案。

常用的模式有:

  • :read - 以讀取模式開啟,檔案必須存在
  • :write - 以寫入模式開啟,檔案不存在時會建立,現有內容會被覆寫
  • :append - 以寫入模式開啟,檔案不存在時會建立,現有內容會保留

完整的模式清單請見 File.open/2的文件。

File.open/2會回傳負責處理這個檔案的行程 PID。要讀寫檔案,請使用 IO模組的函式,並把這個 PID 當作 IO 裝置 傳入。

檔案處理完畢後,請用 File.close/1關閉它。

file = File.open!("README.txt", [:write])
# => #PID<0.157.0>

IO.puts(file, "# README")
# => :ok

File.close(file)
# => :ok

串流檔案

用 File.read/1讀取檔案會一次把整個檔案載入記憶體。處理非常大的檔案時,這可能會是個問題。要有效處理這種檔案,你可以使用 File.open/2和 IO.read/2逐行讀取檔案,也可以用 File.stream/3把檔案串流處理。這個串流同時實作了 Enumerable和 Collectable協定,也就是說它既能用來讀取,也能用來寫入。

File.stream!("file.txt")
|> Stream.map(&(&1 <> "!"))
|> Stream.into(File.stream!("new_file.txt"))
|> Stream.run()

路徑

所有處理檔案的函式都需要檔案路徑。檔案路徑可以是絕對路徑,也可以是相對於目前目錄的路徑。要操作路徑,請使用 Path模組的函式。為了跨平台相容性,請用 Path.join/1建立路徑,它會選擇適合目前平台的分隔符號。

Path.expand(Path.join(["~", "documents", "important.txt"]))
"/home/user/documents/important.txt"
透過 GitHub 編輯 連結會在新視窗或分頁中開啟

學習 File

練習已鎖定

再解鎖 1 個練習,就能練習 File