處理檔案的函式是由File模組提供。
要讀取整個檔案,請使用File.read/1。要寫入檔案,請使用File.write/2。
每次用File.write/2寫入檔案時,都會開啟一個檔案描述符,並生成一個新的 Elixir 行程。因此,應該避免在迴圈中使用File.write/2寫入檔案。
你可以改用File.open/2來開啟檔案。File.open/2的第二個引數是模式陣列,讓你可以指定要以讀取還是寫入的方式開啟檔案。
File.open/2會回傳一個 PID,代表負責處理這個檔案的行程。要讀取和寫入這個檔案,請使用IO模組的函式,並把這個 PID 當作 IO 裝置傳入。
檔案處理完畢後,請使用File.close/1將它關閉。
前面提到的File模組函式都有!版本,會拋出錯誤,而不是回傳錯誤元組(例如File.read!/1)。如果你不打算處理檔案不存在或權限不足之類的錯誤,就使用這個版本。
你是個超級鐵道模型迷,決定開始發行電子報,把你的熱情分享給全世界。首先,你要把電子報的第一期寄給同樣熱愛這項嗜好的朋友和熟人。你有一個文字檔,裡面是他們的電子郵件地址清單。
實作Newsletter.read_emails/1函式。它應該接受一個檔案路徑。這個檔案是純文字檔,裡面是以換行符號分隔的電子郵件地址。這個函式應該回傳檔案中所有電子郵件地址的陣列。
Newsletter.read_emails("/home/my_user/documents/model_train_friends_emails.txt")
# => ["rick@example.com", "choochoo42@example.com", "anna@example.com"]
寄送電子郵件可能因為許多難以預期的原因而失敗,例如電子郵件地址打錯字,或是暫時的網路問題。為了確保你能重試寄送郵件給所有朋友,又不會重複寄送,你需要記錄下已經收到郵件的電子郵件地址。為此,你需要一個日誌檔。
實作Newsletter.open_log/1函式。它應該接受一個檔案路徑,開啟該檔案以寫入,並回傳處理這個檔案的行程 PID。
Newsletter.open_log("/home/my_user/documents/newsletter_issue1_log.txt")
# => #PID<0.145.0>
實作Newsletter.log_sent_email/2函式。它應該接受處理該檔案的行程 PID,以及包含電子郵件地址的字串。它應該把電子郵件地址寫入檔案,後面加上一個換行符號。
Newsletter.log_sent_email(pid, "joe@example.com")
# => :ok
實作Newsletter.close_log/1函式。它應該接受處理該檔案的行程 PID,並關閉該檔案。
Newsletter.close_log(pid)
# => :ok
現在你已經有了寄送郵件流程的所有基礎元件,接著要把這些元件組合成單一個函式。
實作Newsletter.send_newsletter/3函式。它應該接受電子郵件地址檔案的路徑、日誌檔的路徑,以及一個匿名函式,用來把郵件寄給指定的電子郵件地址。它應該從指定的檔案讀取所有電子郵件地址,並嘗試寄送郵件給每一個地址。如果負責寄送郵件的匿名函式回傳:ok,就把該電子郵件地址寫入日誌檔,後面加上一個換行符號。請務必在郵件寄出後立即寫入。所有郵件都寄送完畢後,關閉日誌檔。
Newsletter.send_newsletter(
"model_train_friends_emails.txt",
"newsletter_issue1_log.txt",
fn email -> :ok end
)
# => :ok