二進制配置文件為什么比json等配置文件效率高


二進制配置文件為什么比json等配置文件高效

項目中用spine做動畫,spine可以導出json和二進制的動畫配置文件,蛋疼的是spine官方竟然沒有提供c的二進制配置解析代碼,更沒有提供它二進制文件的格式說明。為了動畫加載的更快,只能自己把json用python轉成二進制文件(格式自定),再自行實現解析二進制的c代碼了。經過小心謹慎的代碼實現后,測試結果是二進制配置文件比json文件大小小了1半以上,並且動畫創建速度快1倍以上。下文簡單總結了一下二進制配置文件的優點。

 

1.什么是二進制配置文件

當然,一切文件在計算機中都是以二進制(01)格式存儲的,那么二進制配置文件是指什么呢?比如要存儲

{
  "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)這樣又可以減少配置文件的大小。

 

2.二進制配置文件優點與缺點

優點已經說了,2個優點:文件小、解析快。為啥文件小上面已經說了。至於為啥解析快呢,首先,因為文件小,io時間需要的就少。其次,少了把配置文件解析成json對象或xml對象的中間步驟,直接讀這個二進制文件就可以,我覺得順着讀二進制文件可以達到最快的速度。

缺點也有2個:難以直接查看、通用性差。json或xml等配置文件可以直接看出來配置的是神馬,可是這個二進制就啥也看不出來了。通用性差是因為要達到高效的解析,最好順着解析,捋一遍配置文件就完了,所以解析二進制的代碼難以公用。

 

3.讀寫二進制例子

比如上面的那個json文件,怎么搞成二進制配置呢,可以先規定好數據的類型,比如s為string,i為number,f為float。string還要告訴解析時字符串有多長,比如time就是s4time。上面的例子要寫二進制就是s4timei133s5colori244i0i0s3posi34i22,這肯定不是最優的,就是為了說明怎么讀寫二進制而已。

 

(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();

執行完會產生下面的二進制文件

 

(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;
}

結果為


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM