LoginSignup
0
2

More than 5 years have passed since last update.

JavaScriptでfloat32のバイナリファイルを読み込む

Posted at

はじめに

JavaScriptでローカルにある単精度浮動小数点数型データ(float32)のバイナリデータを読みこむサンプル。

バイナリデータの作成

まず、C/C++で言うところのfloat型をバイナリで保存する。

test.cpp
#include <cstdio>
#include <cstdlib>
int
main(void){
  const int N=10;
  float a[N];
  for(int i=0;i<N;i++){
    a[i] = 1.1*(i+1);
    printf("%f\n",a[i]);
  }
  FILE *fp = fopen("test.dat","w");
  fwrite((char*)a,sizeof(float),N,fp);
}

コンパイル、実行すると、test.datが生成されるので中身を見てみる。

$ g++ test.cpp
$ ./a.out
$ od -tfF test.dat 
0000000     1.100000e+00    2.200000e+00    3.300000e+00    4.400000e+00
0000020     5.500000e+00    6.600000e+00    7.700000e+00    8.800000e+00
0000040     9.900000e+00    1.100000e+01                                
0000050

1.1から11までの数字がバイナリで保存されている。

JavaScriptでの読み込み

こんなHTMLを書く。

test.html
<!DOCTYPE html>
<html>
<head>
  <title>Float32 Sample</title>
</head>
<body>
<input type="file" id="file" accept=".dat">
<ul id="data"></ul>
<script>
  function onFileSelect(e) {
    var f = e.target.files;
    var reader = new FileReader();
    reader.onload = function(filename){
      a = new Float32Array(reader.result);
      list = $('data');
      var s = "";
      a.forEach(function(v){
        s = s + "<li>" + v.toFixed(6);
      })
      list.innerHTML=s;
    }
    reader.readAsArrayBuffer(f[0]);
  }
  $('file').addEventListener('change', onFileSelect, false);

  function $(id){
    return document.getElementById(id);
  }
</script>
</body>
</html>

処理はこんな感じ。

  • ファイルを読み込むinputタグのchangeイベントに対して、FileReaderオブジェクトreaderreadAsArrayBufferでロードする。
  • readAsArrayBufferは非同期なので、予めreader.onloadにロードが完了した時の処理を書いておく。
  • 読み込まれたデータはreader.resultに貼っているので、それをFloat32Arrayを使ってfloat32の型付き配列として読みこむ。
  • Float32ArrayforEachはコールバック関数を取る。コールバック関数の引数に配列の中身が順番に入ってくるので、ここではそれをリストに追加している。

実行結果

先程のtest.htmlを開くとこんな画面になる。

image.png

参照ボタンを押して、先程作成したtest.datを開くと、中身が表示される。

image.png

ちゃんと読めているようですね。

ハマりポイント

いつくかハマったところなど。

  • ローカルファイルはwindow.onloadなどでは読み込めず、ユーザが明示的に指定する必要がある(セキュリティのため)。
  • Float32Array(reader.result)で読み込んだ配列にたいして、for(var v in a)みたいなfor文を書くと、vString型になってしまい、かつ整数に丸められたものになってしまう。for(var i=0;i<a.length;i++)みたいにしてa[i]でアクセスするのはOK。1

  1. 素直に配列で回すのとコールバック関数使うのとどちらが良いのかは知りません。 

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2