二進制配置文件爲何比json等配置文件效率高

二進制配置文件爲何比json等配置文件高效

項目中用spine作動畫,spine能夠導出json和二進制的動畫配置文件,蛋疼的是spine官方居然沒有提供c的二進制配置解析代碼,更沒有提供它二進制文件的格式說明。爲了動畫加載的更快,只能本身把json用python轉成二進制文件(格式自定),再自行實現解析二進制的c代碼了。通過當心謹慎的代碼實現後,測試結果是二進制配置文件比json文件大小小了1半以上,而且動畫建立速度快1倍以上。下文簡單總結了一下二進制配置文件的優勢。html

 

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

固然,一切文件在計算機中都是以二進制(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.二進制配置文件優勢與缺點

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

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

 

3.讀寫二進制例子

好比上面的那個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;
}

結果爲

相關文章
相關標籤/搜索