大量の浮動小数点数のデータをJavaからバイナリ出力してPythonで読み込む
Javaで処理して作成した大量の浮動小数点数のデータをバイナリでファイル出力して、それをPythonで読み込む方法を確認しました。
Javaからは DataOutputStream
で書き出し、Pythonでは struct.unpack
メソッドで読み込みます。
Javaの DataOutputStream
はハードウェアのバイトオーダーに依存せず、ビッグエンディアンで処理することになっています。従って、Pythonでの読み込み時もビッグエンディアンで読み込むことになります。
- DataOutputStream (Java SE 11 & JDK 11 )
- struct — Interpret bytes as packed binary data — Python 3.9.1 documentation
前回の記事にも似たことを書いてます。
書き出し側サンプルコード
sample1.java
import java.io.BufferedOutputStream; import java.io.DataOutputStream; import java.io.FileOutputStream; import java.io.IOException; class Main { public static void main(String[] args) throws IOException { // 適当な12個の浮動小数点数を作成 double[] arr = new double[12]; for (int i = 0; i < arr.length; i++) { double th = Math.PI / 6 * i; double x = Math.sin(th); arr[i] = x; // 確認のため標準出力 System.out.printf("%f\n", x); } // 倍精度浮動小数点数をビッグエンディアンでファイルに書き出し var dataFilePath = "data.dat"; var output = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(dataFilePath))); for (int i = 0; i < arr.length; i++) { output.writeDouble(arr[i]); } output.close(); } }
実行します。
$ java sample1.java 0.000000 0.500000 0.866025 1.000000 0.866025 0.500000 0.000000 -0.500000 -0.866025 -1.000000 -0.866025 -0.500000
data.dat
が生成されます。サイズを確認すると96バイト。倍精度浮動小数点数は8バイトでそれが12個ですので、あってます。
$ wc -c data.dat 96 data.dat
読み込み側サンプルコード
sample2.py
import struct f = open('data.dat', 'rb') binary = f.read(96) f.close() lst = struct.unpack('>12d', binary) # > : ビッグエンディアン # 12 : 12個連続して読み込む # d : 倍精度浮動小数点数 # 参考 # struct --- バイト列をパックされたバイナリデータとして解釈する — Python 3.9.1 ドキュメント # https://docs.python.org/ja/3/library/struct.html for i in range(12): print(lst[i])
実行します。
$ python sample2.py 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