2009年01月14日

PHPでバイナリデータを解析する場合

どうやってバイナリデータを、計算できる形に持って行くかってはなし。

単なるメモは続きに。

画像などをバイナリデータで読み込んだばあい、そのままだとただのビット列なので扱える形(とりあえず整数)に直さないといけない。 この変換に手間取ったの何のって・・・。

バイナリデータを読み込んだあと、

$file = fopen(FILENAME, 'rb');
flock($file, LOCK_EX);

$data = fread($file, 1); // 1バイト(8ビット)読み込む

とりあえずそのまま使ってみたり→化ける。

echo $data;

sprintfを使ってみたり→整数じゃないから変換できない。

echo sprintf("%b", $data); // 2進数として表示→問答無用で0になる
echo sprintf("%d", $data); // 10進数として表示→同上
echo sprintf("%c", $data); // 文字として表示→なにも表示されない・・・

整数変換してみたり→だから整数じゃないってば。

echo intval($data); // 整数じゃない
echo floatval($data); // 浮動小数点じゃない
echo doubleval($data); // 倍精度浮動小数点でもない
echo strval($data); // 文字列でもない
echo vindec($data); // 2進数でもない

そんなこんなで3時間ほど経ったわけですよ。 途中ニコニコしたりもしてましたが。

答えは結構簡単でした。 今まで「整数からの変換」しか考えてなかったからダメだったわけで。 「ビット列からの変換」を考えればうまくいくわけです。

ビット演算子使って自力で計算してもいいけど、PHPには最初からそんな関数が用意されてます。

echo bin2hex($data);

これで16進数に変換できるので、あとは10進数にするなり32進数にするなり、好きにすればいいわけです。 にしても、数字も文字も、元はビット列のはずなのに、値にかかわらず"0"になったり、なにも表示されなかったりするのはなんでですかね。

09.01.15 17:44追記
コメントにて「ord()」を使えばよいとのアドバイスをいただきました。 次のようにすれば直接10進数の値が取り出せます。

echo ord($data);

データを16進数として使うときはbin2hex()を、10進数として使う場合はord()を使うといいんじゃないでしょうか。
追記ここまで。

あー、もっとうまく検索できるスキルを身につけたい・・・。




同じカテゴリー(プログラミング)の記事画像
GoogleReaderを3ペイン表示にするスクリプトのα版
文字サイズを拡大縮小するスクリプト
電卓を表示するブックマークレット
Twitterで費やした時間を表示するスクリプト
ニコニコのタグをプレビューするスクリプト
ニコニコで広告を消すスクリプト
同じカテゴリー(プログラミング)の記事
 GoogleReaderを3ペイン表示にするスクリプトのα版 (2009-07-26 22:00)
 クリック動作を無効にするジョークブックマークレット (2009-07-19 23:52)
 文字サイズを拡大縮小するスクリプト (2009-07-12 18:09)
 ダブルクリックでスクロールするスクリプト (2009-07-05 14:22)
 電卓を表示するブックマークレット (2009-06-27 21:40)
 ごくごく一部の顔文字を絵文字に置き換えるスクリプト (2009-05-21 23:06)
Posted by Handle at 22:40│Comments(4)プログラミング
この記事へのトラックバック

エントリがあるかと思ったけど、無かったので..._〆(゚▽゚*)
PHPでフォームからのファイルアップロードを処理しましょ。
言語によって微妙に癖が違うからね・・・。




基本事項

P...
PHPの調べ物:ファイルアップロード【美味しいもの】at 2010年11月29日 18:51
この記事へのコメント
freadで得られるのは、CでいうChar型のデータかな。つまりsprintf("%b", $data)はsprintf("%b", "a")と同様の変換をしている(予想)。

試していないけれど、ord($data)で読みだしたデータの整数値が取り出せないかな。もしできればbin2hexよりもordの早いんじゃないかな。
Posted by CTOCTO at 2009年01月15日 02:17
> CTO さん
freadで読み込めるのがchar型なら、
echo sprintf("%c", $data);
で対応する文字が表示されるはずなんですが…。
何も表示されないってのは何でなんでしょうね。

ord($data)も試してみました。
見事バイナリデータから10進数の値が取り出せました。
アドバイスありがとうございます。
Posted by HandleHandle at 2009年01月15日 17:42
sprintf("%c", "a")の結果はaにならないんじゃないかな。%cのときの引数は整数として扱うとマニュアルに書いてあるので。sprintf("%c", 97)≠sprintf("%c", "a")
Posted by CTOCTO at 2009年01月15日 20:49
今更だけどこれじゃ・・・

http://jp.php.net/manual/ja/function.unpack.php
Posted by 今更だけど at 2016年09月03日 23:32
コメントフォーム
上の画像に書かれている文字を入力して下さい
<ご注意>
書き込まれた内容は公開され、ブログの持ち主だけが削除できます。