2018年7月2日 星期一

用Python寫Binary資料

用Python寫Binary資料

前言

  在之前的在Python中使用json,說到了要把Blender匯出的模組輸出成JSON,但如果要匯出模組到C++的話,就勢必要有parse JSON的Library,由於目前不打算引入JSON的Library,所以就想直接使用Python輸出Binary資料,在此把學習過程做個紀錄。

內容

  在學會寫Binary資料要先學會開Binary的檔案,範例如下
import os

f = open("testBinaryData.bin","wb+")
f.write(b"\x01\x02\x03\x04")
f.close()

開啟與寫入的方式和C++是相像的,但是如果要寫一個struct的資料的話,會發現只有write()是不夠用的,如果要寫入像是int、float、double...等資料時會需要一個可以把C++的基本資料型態轉成Python的Bytes這個資料型態的過程,而這個過程就是struct模組。

  接著來看struct模組的使用範例,如下
import struct

structFMT = "iIfd";
packData = struct.pack(structFMT,-1,123,3.14,-3.14 )
print("Pack data:", packData)
print("Pack data type:", type(packData) )
unpackData = struct.unpack(structFMT, packData)
print("Unpack data:", unpackData)
print("Unpack data type:", type(unpackData) )

#output
# Pack data: b'\xff\xff\xff\xff{\x00\x00\x00\xc3\xf5H@\x00\x00\x00\x00\x1f\x85\xebQ\xb8\x1e\t\xc0'
# Pack data type: <class bytes="">
# Unpack data: (-1, 123, 3.140000104904175, -3.14)
# Unpack data type: <class tuple="">

pack()是將資料編成Bytes,unpack()則是將Bytes資料轉回tuple。在這個範例中,pack()與unpack()的第一個參數都是format string,代表資料的格式,目前的格式依序如下
1.int(32位元)
2.unsigned int(32位元)
3.float
4.double
利用format string就可以自己規劃出自己的struct格式,如果想知道format string的詳細資料的話,可以到Interpret strings as packed binary data來了解。在撰寫時擔心float與double這兩個資料型態的Binary格式能不能被C++直接讀取,所以我寫了個C++的程式碼來測試,如下
#include "stdafx.h"
#include "stdio.h"
#include "stdlib.h"
#include "conio.h"
struct STestStruct
{
  long inum;
  unsigned long uinum;
  float fnum;
  double dnum;
};
int main()
{
  STestStruct data;
  FILE* f= fopen("testBinaryData.bin","rb");
  fread(&data,sizeof(STestStruct),1,f);
  printf("%d\n",data.inum);
  printf("%d\n",data.uinum);
  printf("%f\n",data.fnum);
  printf("%LF\n",data.dnum);
  fclose(f);
  system("PAUSE");
  return 0;
}
//output
//-1
//123
//3.140000
//-3.140000

結果非常好,遽然不需要任何轉換就可以讀回來,看來是我多慮了。

參考資料

Interpret strings as packed binary data

沒有留言:

張貼留言