2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Rickyアドカレ2024Advent Calendar 2024

Day 5

elixirのバイナリデータパターンマッチについて理解を深める

Posted at

iex> defmodule WebDB.Binary do
...>   def mime(<<0x89, "PNG", _::bits>>), do: "png"
...>   def mime(<<"GIF", 0x38, _::bits>>), do: "gif"
...>   def mime(<<0xFF, 0xD8, _::bits>>), do: "jpg"
...>   def mime(_), do: "unsupported file"
...> end
{:module, WebDB.Binary, <<(省略)>>, {:mime, 1}}
iex> {:ok, file} = File.read("image.png")
iex> WebDB.Binary.mime(file)
"png"
iex> WebDB.Binary.mime(1)   
"unsupported file"

def mime(<<0x89, "PNG", _::bits>>), do: "png"

なぜ0x89?

以下のサイトにPNGファイルシグネチャについて記載がある

PNG バイナリは、先頭に PNG であることを示す8バイトの識別子があり、その後はチャンクと呼ばれるデータのまとまりが最後まで連なる構造になっています

PNGであることを示す。
16進数で常に、89 50 4E 47 0D 0A 1A 0A

この0x89は16進数で89を示している
そのため同じ値を取得できればそのファイルはPNGであることが判明する
<<>>はバイナリーリテラルを示す

_::bitsは残りのビットをすべて無視する内容となるためPNGファイルでさえあればどんな画像であっても一致する

def mime(<<"GIF", 0x38, _::bits>>), do: "gif"

ここでは引数のGIFが先に来ているがその理由は画像ファイルのマジックナンバーが以下のようになっているためである
image.png

残りのロジックは先ほどと同様

def mime(<<0xFF, 0xD8, _::bits>>), do: "jpg"

JPGの場合は以下

image.png

以下の記事のコードを参考にした

実験

実際に検証してみる
image.png
検証のためにubuntu上へそれぞれの拡張子の画像ファイルを作成した

iex経由で実行を行い正しく取得できているかを確認する

動かした結果
想定通りに動いていることを確認した。
image.png

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?