バイナリファイルの内容を読み出す
次に、バイナリファイルにアクセスして内容を読み出します。テキストファイルの読み込みはreadAsText()メソッドでしたが、バイナリファイルはreadAsBinaryString()メソッドを使います。readAsBinaryString()メソッドは引数にファイルオブジェクトを指定します。
ファイルを読み込む手順はテキストファイルの場合とまったく同じで、読み込んだ内容もテキストと同様にイベントオブジェクトのtarget.resultに入ります。JavaScriptで文字列を扱う場合と同じくcharCodeAt()を使い、読み出したいデータの位置を指定すると任意の1バイトを取り出せます。
実際には以下のようなコードになります。evtはイベントオブジェクトで、ファイルの先頭1バイト目が読み出されます。
data = evt.target.result.charCodeAt(0);
読み出したデータは以下のようにして16進数に変換できます。
data.toString(16)
ここまでをまとめたのがサンプル4です。サンプル4は選択されたファイルの先頭8バイトを16進数で表示します。
<!doctype html>
<head>
<meta charset="utf-8" />
<title>バイナリデータの読み出し</title>
<style type="text/css"><!--
#dumplist { font-family: courier; font-size:11pt; }
--></style>
</head>
<body>
<h1>バイナリデータの読み出し</h1>
<form action="./test.cgi" method="get">
<input type="file" id="myFile" />
<input type="button" id="hexDump" value="先頭8バイトを16進数で表示" />
</form>
<div id="dumplist"></div>
<script>
document.getElementById("hexDump").addEventListener("click", function(){
document.getElementById("dumplist").innerHTML = "";
var fileData = document.getElementById("myFile").files[0];
var reader = new FileReader();
reader.onload = function(evt){
for(var i=0; i<8; i++){
var data = evt.target.result.charCodeAt(i); // 1バイト読み出し
var hex = "0"+data.toString(16);
hex = (hex.substring(hex.length-2, hex.length)).toUpperCase();
document.getElementById("dumplist").innerHTML += hex+"<br />"; // 内容をページ上に表示
}
}
reader.readAsBinaryString(fileData);
}, true);
</script>
</body>
</html>
ダンプリストを表示する
バイナリデータとして1バイト読み出すことができたので、今度はダンプリストを表示する処理を作ります。といっても、あとはファイルサイズ分だけ内容を読み出し、16バイトごとに表示するだけです。今回は一般的なバイナリダンプの形式に倣い、リストの右側に値に対応する文字も表示してみましょう。
データ値としてファイルの内容を読み出すのはcharCodeAt()ですが、文字として読み出す場合は以下のようにcharAt()を使います。
chr = evt.target.result.charAt(i)
完成したスクリプトがサンプル5です。1文字ずつ読み出し表示していくだけなので特に説明は不要でしょう。ただし、サンプル5は文字をHTMLとして出力しているので、テキストに含まれる<、>、&の文字を<のように実体参照に変換することでHTMLタグとして処理されないようにします。
<!doctype html>
<head>
<meta charset="utf-8" />
<title>ダンプリストを表示</title>
<style type="text/css"><!--
#dumplist {
border: 1px solid gray;
font-family: courier; font-size:11pt;
}
span {
color : red;
}
--></style>
</head>
<body>
<h1>ダンプリストを表示</h1>
<form action="./test.cgi" method="get">
<input type="file" id="myFile" />
<input type="button" id="hexDump" value="内容を表示" />
</form>
<div id="dumplist"></div>
<script>
document.getElementById("hexDump").addEventListener("click", function(){
document.getElementById("dumplist").innerHTML = "データを読み込み中...";
var fileData = document.getElementById("myFile").files[0];
var reader = new FileReader();
reader.onload = function(evt){
var count = 0;
var hexlist = "";
var chrlist = "";
var alldata = "";
for(var i=0; i<fileData.size; i++){
var data = evt.target.result.charCodeAt(i); // 1バイト読み出し
var chr = evt.target.result.charAt(i); // 1文字読み出し
if (chr <0x20) { chr = "<span>.</span>"; } // 0x20以下の値は制御コードなので.にする
if (chr == "<") { chr = "<"; } // 不等号記号の処理
if (chr == ">") { chr = ">"; } // 不等号記号の処理
if (chr == "&") { chr = "&"; } // &の処理
var hex = "0"+data.toString(16); // 16進数に変換
hex = (hex.substring(hex.length-2, hex.length)).toUpperCase(); // 2桁の16進数にする
hexlist += hex + " ";
chrlist += chr;
count++;
if (count > 16){ // 横16バイトで区切る
count = 0;
alldata += hexlist+"|"+chrlist+"<br />";
hexlist = chrlist = "";
}
}
document.getElementById("dumplist").innerHTML = alldata; // 内容をページ上に表示
}
reader.readAsBinaryString(fileData);
}, true);
</script>
</body>
</html>