パッキングとアンパッキング:Rubyでバイナリデータを読み取るためのガイド
この記事では、Rubyのパックとアンパックの方法について学習します!
しかし、なぜこれらのメソッドが必要なのですか?
テキストの操作は、バイナリデータの操作よりもはるかに簡単です 。
テキストを使用すると、次を使用できます:
- 正規表現
-
scan
などのメソッド &match
- gsub
ただし、バイナリデータを操作する場合は、追加の作業が必要になります。そこで、Array#packメソッドとString#unpackメソッドが役立ちます。
いくつかの例を示しましょう。単純な文字列から始めて、さらに興味深いものに移ります。
文字列からASCII値へ
これにより、文字列内のすべての文字が10進値に変換されます:
str = "AABBCC" str.unpack("c*") # [65, 65, 66, 66, 67, 67]
"c*"
に注意してください unpack
の引数 。
これは、unpack
に通知する「フォーマット文字列」です。 データをどうするか。この場合、c
つまり、1文字を取り、それを整数値に変換します(String#ordメソッドもこれを行います)。
アスタリスク*
「すべての入力データに対してこの形式を繰り返す」とだけ言ってください。
16進数を文字列に変換
H
pack
で使用 メソッドは、16進数から文字列への変換を提供します。
例 :
["414243"].pack("H*") # "ABC" "ABC".unpack("H*") # ["414243"]
16進数を整数に変換する方法
このフォーマット文字列は4バイトのデータを取り、整数を返します。注意すべき点の1つは、これらのバイトが「リトルエンディアン」形式であるということです。
例 :
"\xff\x00\x00\x00".unpack("l").first # 255
"\x90\xC0\xDD\x08".unpack("l").first # 148750480
first
を使用しました unpack
のためここに 配列を返します。
Unpackメソッドを使用したバイナリファイルの解析
EXE、PNG、GZIPなどのバイナリファイルをどのように読み取りますか?
これらのファイルをプレーンテキストのように読むと、ランダムなデータのように見えるものが表示されます…
ランダムなものではありません。
文書化された構造があります これらのファイル形式の多くとunpack
メソッドは、そのデータを読み取り、それを有用なものに変換するために使用できるものです。
ここに例があります :
binary_data = "\x05\x00\x68\x65\x6c\x6c\x6f" length, message = binary_data.unpack("Sa*") # [5, "hello"]
この例では、バイナリデータ(16進数で表され、1と0よりもはるかにコンパクトです)には、次の文字列の長さを含む2バイト(16ビット)の長さフィールドがあります。次に、文字列自体があります。
バイナリファイルとバイナリネットワークプロトコルに「長さ」フィールドがあることは非常に一般的です。
これはパーサーに正確に何バイトを読み取る必要があるかを通知します 。
はい。
この例では、長さとデータの両方を1つのステップで読み取ることがわかっています。これは、物事を単純にするためです。
BinDataGemの使用方法
バイナリ構造の解析を支援するために特別に構築されたbindatagemもあります。
ここに例があります :
class BinaryString < BinData::Record endian :little uint16 :len string :name, :read_length => :len end
read_length
に注意してください パラメータ。これにより、bindataにフィールドからの長さを計算するように指示されるため、多くの作業を節約できます🙂
したがって、任意のバイナリ形式のパーサーを作成する場合は、次の手順を実行します。
- この形式の仕様を見つけます(公開されていない場合は、リバースエンジニアリングする必要があります。これはそれ自体がトピック全体です)
- ファイルのすべてのセクションに`bindata`クラスを記述します(通常、最初にメタデータを含むヘッダーセクションがあり、次に複数のデータセクションがあります)
- データを読み取り、必要に応じて処理します(たとえば、PNGでは画像の色を変更できます)
- 利益!
bindata
の完全な例を見たい場合 実際には、githubで私のPNGパーサーを見てください。
Base64エンコーディング
「Base64」と呼ばれるこのタイプのエンコーディングがあります。以前にURLで見たことがあるかもしれません。
このように見えます :
U2VuZCByZWluZm9yY2VtZW50cw==
最後のdoubleequalsは通常、Base64
を扱っていることを示す兆候です。 、ただし、一部の入力では等号が表示されない場合があります(パディングとして使用されます)。
それで、なぜ私があなたにこれを言っているのか…
単独で知っておくと便利なことであることに加えて?
文字列をBase64
に変換できることがわかりました pack
を使用する メソッド。
ここに表示されているように :
def encode64(bin) [bin].pack("m") end encode64 "abcd" # "YWJjZA==\n"
実際、これはBase64
で使用されている正確な方法です。 標準ライブラリのモジュール。
概要
この投稿では、pack
について学びました &unpack
バイナリデータの操作に役立つメソッド。これを使用して、バイナリファイルの解析、文字列のASCII値への変換、およびBase64エンコーディングを行うことができます。
共有して購読することを忘れないでください このようなブログ投稿をもっと楽しむことができます! 🙂
-
Rubyの入出力(IO):決定的なガイド
I/Oは入力/出力の略です。 入力とは、何か(コンピューター、Rubyメソッド、脳)に入力されるすべてのデータと情報を意味します。 入力の例 : キーボードのプレスキーを押します マウスクリック 読んだ本 出力とは、入力の結果として出てくるすべてのものを意味します。 出力の例 : 1+1の結果 読んだ記事の要約を書く コーヒー Rubyでは、I / Oについて話すとき、通常、ファイルの読み取り、ネットワークソケットの操作、画面への情報の印刷を指します。 IOクラスを理解する IOはRubyのクラスでもあります。 Fileなどの他のオブジェクトの親クラスです &Socke
-
Rubyでの関数型プログラミング(完全ガイド)
関数型プログラミングについて聞いたばかりで、いくつか質問があるかもしれません。 いいね… 関数型プログラミングとは正確には何ですか? オブジェクト指向プログラミングと比較してどうですか? Rubyで関数型プログラミングを使用する必要がありますか? これらの質問に答えて、これがどのように機能するかをよりよく理解できるようにします。 関数型プログラミングとは これは単なる流行や派手な言葉ではなく、長い間存在していた実際のプログラミングパラダイムですが、最近人気を取り戻しています。 そして、このパラダイムの背後にある基本的な考え方は、あなたが思っているよりも理解しやすいです。 関数型