base64のこと
base64というエンコード方法がある。
元のデータを6bitsずつに切って、64種類の文字を割り当てるという方法。
割り当てられる文字はアスキーコードの1byte文字なので8bitsということで、単純には6bitsが8bitsになるのでファイルサイズが33%アップする。
他に細かい理由でもうちょっと大きくなるけど、俺は気にしない。
ファイルサイズが大きくなる変換だけど、アスキーコードに変換されて文字列として扱えるため、何かと扱いやすい。
おそらく一番よく見るのがメールへのファイル添付。
SMTPを使ったメールは7bitsの文字、つまりアスキーコードの頭がゼロの部分しか使えないらしい。
base64で使われる文字は全部7bitsのとこだから、これで送れるというわけ。
他にもたとえば、文字しかかけない掲示板なんかに、ファイルをbase64でエンコードした文字列を投稿すれば、閲覧者はそれをbase64でデコードすれば元のファイルに戻すことが出来るわけだ。
実験内容
で、今回はbase64を使って、データベースのデータ型がtextになってるところにファイルを書き込むというのをやってみた。
実験方法
実行環境はPHP、データベースはPostgreSQLを使う。
どんぐらい時間がかかるのかって興味もあるので、ちょっと大きめの2MBぐらいの写真をfile()で読み込んで、base64_encode()でエンコードする。
これをデータベースに書き込んで、更にそれをデータベースから読み出して、base64_decode()でデコードする。
これを、fputs()でファイルに書き込んで、出来上がったファイルの検証と、各々の処理にかかった時間を計る。
ソース
データベースのテーブル定義は、
こんだけ。
PHPのソースは、
//時刻取得用関数
include("getmicrotime.php");
//処理前の時刻
$time[] = getmicrotime();
//画像ファイルを読み込む
$data = file("./base64_input.jpg");
//改行コードに相当するもので区切られて配列に格納されるので、
//一つの変数にまとめてやる。
$data = implode(null,$data);
//ファイル読み込みしたときの時刻
$time[] = getmicrotime();
$com[] = "fread";
//base64でエンコードしてやる。
//これでASCIIデータになる。
$data = base64_encode($data);
//エンコード完了したときの時刻
$time[] = getmicrotime();
$com[] = "encode";
//これを一旦データベースに保存してやる。
echo "pgsql1:";
var_dump($pg = pg_connect("host=localhost user=genkikko"));
echo "<br>write:";
var_dump(pg_query($pg,"update base64 set data = '$data' where num = 0;"));
pg_close($pg);
echo "<br><br>\n";
//データベースに保存完了したときの時刻
$time[] = getmicrotime();
$com[] = "dbwrite";
//そしてデータベースからデータを読み出して変数にまとめる。
echo "pgsql2:";
var_dump($pg = pg_connect("host=localhost user=genkikko"));
echo "<br>read:";
var_dump($data = pg_query($pg,"select data from base64 where num = 0;"));
$data = pg_fetch_array($data);
pg_close($pg);
$data = $data[0];
echo "<br><br>\n";
//データベースから読み出したときの時刻
$time[] = getmicrotime();
$com[] = "dbread";
//エンコードされたデータの中身を覗いてみる。
//でっかいので最初の512バイトだけで勘弁。
echo substr($data,0,512);
echo "<br><br>\n";
//デコードして元のデータに変換。
$data = base64_decode($data);
//デコード完了したときの時間
$time[] = getmicrotime();
$com[] = "decode";
//出力用のファイルを空にして開いて、
//デコードされたデータを書き込む。
echo "output:";
var_dump($fp = fopen("base64_output.jpg",'w'));
fputs($fp,$data);
fclose($fp);
echo "<br><br>\n";
//処理後の時刻
$time[] = getmicrotime();
$com[] = "fwrite";
//かかった時間を表示
echo "<table border=1>\n";
for($i=1;$time[$i];$i++){
echo "<tr><td>";
echo $com[$i-1];
echo "</td><td>";
echo round($time[$i] - $time[$i-1],4);
echo "[s]</td></tr>\n";
}
$time = round($time[$i-1]-$time[0],4);
echo "<tr><td>total</td><td>{$time}[s]</td></tr>\n";
echo "</table>";
?>
実行すると、1.5秒ぐらいかかる。
しかし、そのうち1秒ぐらいがデータベースへの書き込みにかかってる。
さぁ、この結果から何を考察しようか。