學習軌道
/
Elixir
Elixir
/
練習
/
檔案嗅探器
檔案嗅探器

檔案嗅探器

學習練習

簡介

二進位

Elixir 提供了優雅的語法來處理二進位資料,就像我們用來處理位元字串的<<>>特殊形式一樣。

二進位型別是位元字串型別的一種特化。位元字串的長度可以是任意的(任意數量的位元),而二進位的位元數量則必須能被 8 整除。也就是說,在處理二進位時,我們通常會以位元組(8 個位元)為單位來思考。一個位元組可以表示從0到255的整數。我們經常以十六進位處理位元組的值,也就是0x00 - 0xFF。

二進位字面值是使用位元字串的特殊形式<<>>定義的。定義二進位字面值時,我們可以使用整數和字串字面值。大於 255 的整數值會溢位,只會使用該整數的最後 8 個位元。預設情況下,該值會套用::binary修飾詞。我們可以用<>/2運算子串接二進位。

<<255>> == <<0xFF>>
# Overflowing bits are truncated
<<256>> == <<0>>
<<2, 4, 6, 8, 10, 12, 14, 16>> == <<0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, 0x10>>

null-byte 是<<0>>的另一個名稱。

二進位資料的模式匹配

模式匹配甚至可以套用到二進位上,我們可以針對二進位資料的某一部分進行模式匹配,就像我們對陣列所做的那樣。

# Ignore the first 8 bytes, match and bind the remaining to `body`
<<_::binary-size(8), body::binary>>

就像其他型別的模式匹配一樣,我們可以把這種寫法用在函式簽章裡,讓程式從多個函式子句中挑選符合的那一個。

說明

你正在進行一個專案,這個專案讓使用者可以把檔案上傳到伺服器,與其他使用者分享。你被指派要寫一個函式,驗證上傳的檔案是否符合它的媒體類型。你查了一些資料後發現,檔案的前幾個位元組通常對該檔案類型來說是獨一無二的,就像是它的一種簽章。

請參考下表:

檔案類型 常見副檔名 媒體類型 二進位「簽章」
ELF "exe" "application/octet-stream" 0x7F, 0x45, 0x4C, 0x46
BMP "bmp" "image/bmp" 0x42, 0x4D
PNG "png" "image/png" 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A
JPG "jpg" "image/jpg" 0xFF, 0xD8, 0xFF
GIF "gif" "image/gif" 0x47, 0x49, 0x46

1. 給定副檔名,回傳預期的媒體類型

實作type_from_extension/1函式。它應該接受一個副檔名(字串),並回傳媒體類型(字串),如果副檔名不符合預期的那些,則回傳 nil。

FileSniffer.type_from_extension("exe")
# => "application/octet-stream"

FileSniffer.type_from_extension("txt")
# => nil

2. 給定二進位檔,回傳預期的媒體類型

實作type_from_binary/1函式。它應該接受一個檔案(二進位),並回傳媒體類型(字串),如果檔案簽章不符合預期的那些,則回傳 nil。

file = File.read!("application.exe")
FileSniffer.type_from_binary(file)
# => "application/octet-stream"

file = File.read!("example.txt")
FileSniffer.type_from_binary(file)
# => nil

不用擔心要把檔案讀取成二進位,就假設這件事已經幫你做好了,測試會把它當作引數傳進來。

3. 給定副檔名和二進位檔,驗證檔案是否符合預期的類型

實作verify/2函式。它應該接受一個檔案(二進位)和副檔名(字串),並回傳:ok或:error元組。

file = File.read!("application.exe")

FileSniffer.verify(file, "exe")
# => {:ok, "application/octet-stream"}

FileSniffer.verify(file, "png")
# => {:error, "Warning, file format and file extension do not match."}
透過 GitHub 編輯 連結會在新視窗或分頁中開啟
Elixir Exercism

準備好開始 檔案嗅探器 了嗎?

註冊 Exercism,透過 58 個概念168 個練習 和真人引導來學習並精通 Elixir,全部免費。