Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

パッキングとアンパッキング: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などのバイナリファイルをどのように読み取りますか?

これらのファイルをプレーンテキストのように読むと、ランダムなデータのように見えるものが表示されます…

パッキングとアンパッキング:Rubyでバイナリデータを読み取るためのガイド

ランダムなものではありません。

文書化された構造があります これらのファイル形式の多くと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にフィールドからの長さを計算するように指示されるため、多くの作業を節約できます🙂

したがって、任意のバイナリ形式のパーサーを作成する場合は、次の手順を実行します。

  1. この形式の仕様を見つけます(公開されていない場合は、リバースエンジニアリングする必要があります。これはそれ自体がトピック全体です)
  2. ファイルのすべてのセクションに`bindata`クラスを記述します(通常、最初にメタデータを含むヘッダーセクションがあり、次に複数のデータセクションがあります)
  3. データを読み取り、必要に応じて処理します(たとえば、PNGでは画像の色を変更できます)
  4. 利益!

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エンコーディングを行うことができます。

共有して購読することを忘れないでください このようなブログ投稿をもっと楽しむことができます! 🙂


  1. Rubyの入出力(IO):決定的なガイド

    I/Oは入力/出力の略です。 入力とは、何か(コンピューター、Rubyメソッド、脳)に入力されるすべてのデータと情報を意味します。 入力の例 : キーボードのプレスキーを押します マウスクリック 読んだ本 出力とは、入力の結果として出てくるすべてのものを意味します。 出力の例 : 1+1の結果 読んだ記事の要約を書く コーヒー Rubyでは、I / Oについて話すとき、通常、ファイルの読み取り、ネットワークソケットの操作、画面への情報の印刷を指します。 IOクラスを理解する IOはRubyのクラスでもあります。 Fileなどの他のオブジェクトの親クラスです &Socke

  2. Rubyでの関数型プログラミング(完全ガイド)

    関数型プログラミングについて聞いたばかりで、いくつか質問があるかもしれません。 いいね… 関数型プログラミングとは正確には何ですか? オブジェクト指向プログラミングと比較してどうですか? Rubyで関数型プログラミングを使用する必要がありますか? これらの質問に答えて、これがどのように機能するかをよりよく理解できるようにします。 関数型プログラミングとは これは単なる流行や派手な言葉ではなく、長い間存在していた実際のプログラミングパラダイムですが、最近人気を取り戻しています。 そして、このパラダイムの背後にある基本的な考え方は、あなたが思っているよりも理解しやすいです。 関数型