Track
/
Elixir
Elixir
/
Esercizi
/
Sniffer di file
Sniffer di file

Sniffer di file

Esercizio di apprendimento

Introduzione

Binari

Elixir offre una sintassi elegante per lavorare con i dati binari, come abbiamo visto con la forma speciale <<>> pensata per lavorare con i bitstring.

Il tipo binary è una specializzazione del tipo bitstring. I bitstring possono avere qualsiasi lunghezza (qualsiasi numero di bit); i binari, invece, sono quelli in cui il numero di bit è divisibile per 8. Quando lavoriamo con i binari, infatti, pensiamo spesso in termini di byte (8 bit). Un byte può rappresentare numeri interi da 0 a 255. È comune lavorare con valori di byte in esadecimale, 0x00 - 0xFF.

I valori letterali binari si definiscono con la forma speciale per i bitstring <<>>. Quando definiamo un valore letterale binario, possiamo usare valori letterali interi e stringhe. I valori interi maggiori di 255 vanno in overflow e vengono usati solo gli ultimi 8 bit dell'intero. Per impostazione predefinita, al valore viene applicato il modificatore ::binary. Possiamo concatenare i binari con l'operatore <>/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>>

Un null-byte è un altro nome per <<0>>.

Pattern matching sui dati binari

Il pattern matching è persino esteso ai binari: possiamo applicarlo a una porzione di dati binari, proprio come faremmo con un array.

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

Come per gli altri tipi di pattern matching, possiamo usarlo nelle firme delle funzioni per scegliere tra più clausole di funzione.

Istruzioni

Hai lavorato a un progetto che consente agli utenti di caricare file sul server per condividerli con altri utenti. Ti è stato chiesto di scrivere una funzione per verificare che un caricamento corrisponda al suo tipo di media. Fai qualche ricerca e scopri che i primi byte di un file sono generalmente unici per quel tipo di file, una sorta di firma.

Usa la tabella seguente come riferimento:

Tipo di file Estensione comune Tipo di media «firma» binaria
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. Data un'estensione, restituisci il tipo di media previsto

Implementa la funzione type_from_extension/1. Deve accettare un'estensione di file (stringa) e restituire il tipo di media (stringa) oppure nil se l'estensione non corrisponde a quelle previste.

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

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

2. Dato un file binario, restituisci il tipo di media previsto

Implementa la funzione type_from_binary/1. Deve accettare un file (binario) e restituire il tipo di media (stringa) oppure nil se la firma del file non corrisponde a quelle previste.

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

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

Non preoccuparti di leggere il file come binario. Dai per scontato che sia già stato fatto e che i test lo forniscano come argomento.

3. Data un'estensione e un file binario, verifica che il file corrisponda al tipo previsto

Implementa la funzione verify/2. Deve accettare un file (binario) e un'estensione (stringa) e restituire una tupla :ok o :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."}
Modifica tramite GitHub Il link si apre in una nuova finestra o scheda
Elixir Exercism

Vuoi iniziare Sniffer di file?

Iscriviti a Exercism per imparare e padroneggiare Elixir con 58 concetti168 esercizi e il mentoring di persone reali, tutto gratis.