便利ページ:Javascriptでちょっとした便利な機能を作ってみた のシリーズものです。
今回は、Javascsript上でバイナリファイルを開いたり、バイナリファイルに保存したりしてみます。
他の有志のページで、たくさんの情報がありましたので、非常に助かりました。
毎度の通り、デモページとGitHubです。
GitHub
https://github.com/poruruba/utilities
デモページ
https://poruruba.github.io/utilities/
バイナリファイルを開く
HTMLのtype="file"のinput要素を使います。
このinputのボタンによりファイルを選択されたイベントをフックし、あとはHTML5のFile機能を使います。
<input type="file" v-on:change="binary_open" v-on:click="binary_click"><br>
<button v-on:click="binary_save()">ファイルに保存</button><br>
<br>
<div class="form-inline">
<label>改行</label>
<select class="form-control" v-model="binary_cr_num">
<option value="0">無し</option>
<option value="2">2バイト</option>
<option value="4">4バイト</option>
<option value="8">8バイト</option>
<option value="16">16バイト</option>
</select>
<input type="checkbox" v-model="binary_space">空白
<button class="btn btn-primary" v-on:click="binary_cr()">整形</button><br>
</div>
<textarea class="form-control" rows="5" v-model="binary_output"></textarea>
type="file"のファイルが指定されると、Vueの構文でv-on:changeで指定した関数(binary_open)が呼ばれます。
ArrayBufferとして読み出して、読み出しが完了したときに、16進数文字列にして表示させています。
binary_open: function(e){
var file = e.target.files[0];
var reader = new FileReader();
reader.onload = (theFile) =>{
this.binary_output = byteAry2hexStr(new Uint8Array(theFile.target.result));
};
reader.readAsArrayBuffer(file);
},
binary_click: function(e){
e.target.value = '';
},
一方、v-on:clickで関数(binary_click)を指定しています。
これは、一度ファイルを選択した後に、再度同じファイルを選択してもonchangeが呼ばれないため、ファイル選択ボタンを押したときに、以前に選択していたファイルを未選択状態にしています。
バイナリファイルを保存
バイナリファイルの保存は、以下の関数です。
binary_save: function(){
var target = this.binary_output.replace(/\r?\n|\s/g, '');
var array = hexStr2byteAry(target);
var buffer = new ArrayBuffer(array.length);
var dv = new DataView(buffer);
for( var i = 0 ; i < array.length ; i++ )
dv.setUint8(i, array[i]);
var blob = new Blob([buffer], {type: "octet/stream"});
var url = window.URL.createObjectURL(blob);
var a = document.createElement("a");
a.href = url;
a.target = '_blank';
a.download = "array.bin";
a.click();
window.URL.revokeObjectURL(url);
},
最初に、改行と空白を削除しています。それは後述する整形を想定してのことです。整形を実行したときに改行やスペースを挿入して表示しているためです。
16進数文字列を整形する
長いバイト列を16進数文字列で表示させると見にくくなります。
そこで、適当に改行を入れたり、1バイトごとに空白を入れたりしています。例えば、16バイトごとに改行を入れるなど。
binary_cr: function(){
var target = this.binary_output.replace(/\r?\n|\s/g, '');
var array = hexStr2byteAry(target);
var num_of_interval = Number(this.binary_cr_num);
if( num_of_interval == 0 ){
if( this.binary_space )
this.binary_output = byteAry2hexStr(array, ' ');
else
this.binary_output = byteAry2hexStr(array);
}else{
var str = '';
for( var i = 0 ; i < array.length ; i += num_of_interval ){
if( this.binary_space )
str += byteAry2hexStr(array.slice( i, i + num_of_interval ), ' ') + '\n';
else
str += byteAry2hexStr(array.slice( i, i + num_of_interval )) + '\n';
}
this.binary_output = str;
}
},
以上