項目中用spine作動畫,spine能夠導出json和二進制的動畫配置文件,蛋疼的是spine官方居然沒有提供c的二進制配置解析代碼,更沒有提供它二進制文件的格式說明。爲了動畫加載的更快,只能本身把json用python轉成二進制文件(格式自定),再自行實現解析二進制的c代碼了。通過當心謹慎的代碼實現後,測試結果是二進制配置文件比json文件大小小了1半以上,而且動畫建立速度快1倍以上。下文簡單總結了一下二進制配置文件的優勢。html
固然,一切文件在計算機中都是以二進制(01)格式存儲的,那麼二進制配置文件是指什麼呢?好比要存儲python
{ "time" = 133, "color" = [233, 0, 0], "pos" = [34, 22] }
json通常以utf-8格式保存成文本,那麼什麼是utf-8呢?它是unicode編碼的一種實現形式,具體解釋請參考UTF-8編碼規則(轉),中日韓uincode編碼參考。也就是說,像程序中的數字類型133,233,22等,一個uint8就能存儲下了,但是133在json中卻佔了3個字節,要是存個12.432312等數據要佔用更多的空間。而本文所說的二進制配置,直接存133等的uint8二進制編碼0x85,這樣便減小了一部分文件大小。編碼與解碼能夠商量好,好比time,編解碼都以t代替,又能夠節省一部分空間,甚至能夠不存儲time,color,pos等key,直接順序在配置中寫value,解碼時直接讀value(爲了說的清楚,後面的例子保留了key)這樣又能夠減小配置文件的大小。ios
優勢已經說了,2個優勢:文件小、解析快。爲啥文件小上面已經說了。至於爲啥解析快呢,首先,由於文件小,io時間須要的就少。其次,少了把配置文件解析成json對象或xml對象的中間步驟,直接讀這個二進制文件就能夠,我以爲順着讀二進制文件能夠達到最快的速度。c++
缺點也有2個:難以直接查看、通用性差。json或xml等配置文件能夠直接看出來配置的是神馬,但是這個二進制就啥也看不出來了。通用性差是由於要達到高效的解析,最好順着解析,捋一遍配置文件就完了,因此解析二進制的代碼難以公用。json
好比上面的那個json文件,怎麼搞成二進制配置呢,能夠先規定好數據的類型,好比s爲string,i爲number,f爲float。string還要告訴解析時字符串有多長,好比time就是s4time。上面的例子要寫二進制就是s4timei133s5colori244i0i0s3posi34i22,這確定不是最優的,就是爲了說明怎麼讀寫二進制而已。post
(1)python寫二進制文件測試
python寫二進制文件用到了 struct.pack,讀二進制用 struct.unpack(),具體怎用用struct請參考 使用Python進行二進制文件讀寫 動畫
Format | C Type | Python | 字節數 |
---|---|---|---|
x | pad byte | no value | 1 |
c | char | string of length 1 | 1 |
b | signed char | integer | 1 |
B | unsigned char | integer | 1 |
? | _Bool | bool | 1 |
h | short | integer | 2 |
H | unsigned short | integer | 2 |
i | int | integer | 4 |
I | unsigned int | integer or long | 4 |
l | long | integer | 4 |
L | unsigned long | long | 4 |
q | long long | long | 8 |
Q | unsigned long long | long | 8 |
f | float | float | 4 |
d | double | float | 8 |
s | char[] | string | 1 |
p | char[] | string | 1 |
P | void * | long |
import struct def writeBinary(): binaryFile = open(r"./binary.obj","wb"); binaryFile.write(struct.pack("i", 4)); binaryFile.write(struct.pack("4s", "time")); binaryFile.write(struct.pack("i", 133)); binaryFile.write(struct.pack("i", 5)); binaryFile.write(struct.pack("5s", "color")); if __name__ == "__main__": writeBinary();
執行完會產生下面的二進制文件ui
(2)c++讀二進制文件編碼
#include <iostream> using namespace std; char * data = nullptr; char * getFileContent(const char * filePath) { FILE *pFile=fopen(filePath, "r"); char * pBuf; fseek(pFile, 0, SEEK_END); int len = ftell(pFile); pBuf = new char[len+1]; rewind(pFile); fread(pBuf, 1, len, pFile); pBuf[len] = 0; fclose(pFile); return pBuf; } int8_t readByte() { return (int8_t)*data++; } int32_t readInt() { int32_t val = 0; char * pd = (char*)&val; *pd = readByte(); *(pd + 1) = readByte(); *(pd + 2) = readByte(); *(pd + 3) = readByte(); return (int32_t)val; } std::string readString() { int32_t strLen = readInt(); std::string str = std::string(data, strLen); data = data + strLen; return str; } int main() { data = getFileContent("/Users/abc/PycharmProjects/BinaryTest/binary.obj"); std::string timeStr = readString(); int timeValue = readInt(); std::string colorStr = readString(); std::cout << "timeStr is " << timeStr << std::endl; std::cout << "colorStr is " << colorStr << std::endl; std::cout << "timeValue is " << timeValue << std::endl; free(data); return 0; }
結果爲