Trilhas
/
Elixir
Elixir
/
Exercícios
/
Detector de arquivos
Detector de arquivos

Detector de arquivos

Exercício de aprendizagem

Introdução

Binários

O Elixir oferece uma sintaxe elegante para trabalhar com dados binários, como já vimos com a forma especial <<>> usada para trabalhar com bitstrings.

O tipo binário é uma especialização do tipo bitstring. Enquanto bitstrings podem ter qualquer comprimento (qualquer quantidade de bits), binários têm um número de bits divisível por 8. Ou seja, ao trabalhar com binários, costumamos pensar em termos de bytes (8 bits). Um byte pode representar números inteiros de 0 a 255. É comum trabalhar com valores de byte em hexadecimal, 0x00 - 0xFF.

Literais binários são definidos usando a forma especial de bitstring <<>>. Ao definir um literal binário, podemos usar literais inteiros e strings. Valores inteiros maiores que 255 sofrem overflow e apenas os últimos 8 bits do inteiro são usados. Por padrão, o modificador ::binary é aplicado ao valor. Podemos concatenar binários com o operador <>/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>>

Um byte nulo é outro nome para <<0>>.

Casamento de padrões em dados binários

O casamento de padrões é estendido até mesmo a binários, e podemos fazer casamento de padrões sobre uma parte dos dados binários, assim como faríamos com uma lista.

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

Assim como em outros tipos de casamento de padrões, podemos usar isso em assinaturas de função para fazer a correspondência ao selecionar entre várias cláusulas de função.

Instruções

Você tem trabalhado em um projeto que permite que usuários enviem arquivos para o servidor para serem compartilhados com outros usuários. Você recebeu a tarefa de escrever uma função para verificar se um arquivo enviado corresponde ao seu tipo de mídia. Você faz uma pesquisa e descobre que os primeiros bytes de um arquivo geralmente são únicos para aquele tipo de arquivo, o que lhe dá uma espécie de assinatura.

Use a tabela a seguir como referência:

Tipo de arquivo Extensão comum Tipo de mídia assinatura binária
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. Dada uma extensão, retorne o tipo de mídia esperado

Implemente a função type_from_extension/1. Ela deve receber uma extensão de arquivo (string) e retornar o tipo de mídia (string) ou nil se a extensão não corresponder às esperadas.

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

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

2. Dado um arquivo binário, retorne o tipo de mídia esperado

Implemente a função type_from_binary/1. Ela deve receber um arquivo (binário) e retornar o tipo de mídia (string) ou nil se a assinatura do arquivo não corresponder às esperadas.

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

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

Não se preocupe em ler o arquivo como binário. Considere que isso já foi feito para você e que é fornecido pelos testes como argumento.

3. Dada uma extensão e um arquivo binário, verifique se o arquivo corresponde ao tipo esperado

Implemente a função verify/2. Ela deve receber um arquivo (binário) e uma extensão (string) e retornar uma tupla :ok ou :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."}
Editar via GitHub O link abre em uma nova janela ou aba
Elixir Exercism

Tudo pronto para começar Detector de arquivos?

Crie sua conta no Exercism para aprender e dominar Elixir com 58 conceitos168 exercícios e mentoria humana de verdade, tudo de graça.