大量の浮動小数点数のデータをRubyからバイナリ出力してJavaで読み込む
Rubyで処理して作成した大量の浮動小数点数のデータをバイナリでファイル出力して、それをJavaで読み込む方法を確認しました。
Rubyからはpack
メソッドで書き出し、Javaでは DataInputStream
で読み込みます。
Javaの DataInputStream
はハードウェアのバイトオーダーに依存せず、ビッグエンディアンで処理することになっています。従って、Rubyからの出力時もビッグエンディアンで書き出すことにします。
翌日追記:翌日にも似たことを書いてます。
- Ruby→Java (今回)
- Java→Python (翌日)
書き出し側サンプルコード
sample1.rb
dataFilePath = "data.dat" # 適当な12個の浮動小数点数を作成 arr = [] for i in 0..11 th = Math::PI / 6 * i x = Math.sin(th) arr.push(x) end # 確認のため標準出力 arr.each do |x| puts(x) end # 倍精度浮動小数点数をビッグエンディアンでファイルに書き出し buf = arr.pack("G12") # Gはビッグエンディアンの倍精度浮動小数点数の意味 File.open(dataFilePath, "w") do |fp| fp.write(buf) end
実行します。
$ ruby sample1.rb 0.0 0.49999999999999994 0.8660254037844386 1.0 0.8660254037844387 0.5000000000000003 1.2246467991473532e-16 -0.4999999999999997 -0.8660254037844384 -1.0 -0.866025403784439 -0.5000000000000004
data.dat
が生成されます。サイズを確認すると96バイト。倍精度浮動小数点数は8バイトでそれが12個ですので、あってます。
$ wc -c data.dat 96 data.dat
読み込み側サンプルコード
JavaといいつつサンプルコードはScalaです。Javaでもやりかたは同じです。
sample2.scala
import java.io.BufferedInputStream; import java.io.DataInputStream; import java.io.FileInputStream; val dataFilePath = "data.dat"; // ファイルから読み込んで確認のため標準出力 val input = new DataInputStream(new BufferedInputStream(new FileInputStream(dataFilePath))); (0 until 12).foreach { _ => val x = input.readDouble(); println(x); }
実行します。
$ scala sample2.scala 0.0 0.49999999999999994 0.8660254037844386 1.0 0.8660254037844387 0.5000000000000003 1.2246467991473532E-16 -0.4999999999999997 -0.8660254037844384 -1.0 -0.866025403784439 -0.5000000000000004