JS 位元組流 解析

逆-血發表於2020-12-07


前言

提示:最近作者在工作之餘,遇到了關於位元組資料傳輸,前端解析資料的問題,為此寫了一個用於處理該類問題的 js 庫。


提示:以下是本篇文章正文內容,下面案例可供參考

JS 原始碼

程式碼如下(示例):

var BOOL_TYPE = 0,       // Bool
    INT8_TYPE = 1,       // Char
    UINT8_TYPE = 2,      // UChar
    INT16_TYPE = 3,      // Short
    UINT16_TYPE = 4,     // UShort
    INT32_TYPE = 5,      // Int
    INT64_TYPE = 6       // Long
    UINT32_TYPE = 7,     // UInt
    FLOAT32_TYPE = 8,    // Float
    FLOAT64_TYPE = 9,    // Double
    BYTE_TYPE = 10,      // Byte
    Str_TYPE = 11;  
    
// type:資料型別, Bin:二進位制流,begin:資料起始位置(位元組),Num: 1
function TypedArrays(Type, Bin) {//, begin, Num
    //var _num = 1;
    switch (Type) {
        case BOOL_TYPE: return Bin[0] == 1 ? true : false;
        case INT8_TYPE: return toInt8(Bin); 
        case UINT8_TYPE: return toUint8(Bin); 
        case INT16_TYPE: return toInt16(Bin);    
        case UINT16_TYPE: return toUint16(Bin);  
        case INT32_TYPE: return toInt32(Bin);    
        case INT64_TYPE: return toInt64(Bin);    
        case UINT32_TYPE: return toUint32(Bin);  
        case FLOAT32_TYPE: return toFloat32(Bin);
        case FLOAT64_TYPE: return toFloat64(Bin);
        case BYTE_TYPE: return toBytes(Bin);
        case Str_TYPE: return toString(Bin);
        default: return -1;
    }
}

// 擷取指定大小資料並轉換成指定的資料型別
function ByteToType(Type, Bin, begin, Num) {
    return TypedArrays(Type, Bin.splice(begin, Num));//, begin, Num);
}

// ASCII to char
function ASCII2Char(v) { return String.fromCharCode(v); }

// ASCII to string
function ASCII2Str(Bin, StartByte, Type, MsgLen) {
    var MsgName = "";
    var Index = 0;

    while (Index < MsgLen) {
        var AsciiValue = TypedArrays(Type, Bin, StartByte, 1); StartByte += 1;
        if (AsciiValue != 0)
            MsgName += ASCII2Char(AsciiValue);
        else
            return MsgName;
        Index++;
    }
    return MsgName;
}
function byteToString(arr) {
    if (typeof arr === 'string') {
        return arr;
    }
    var str = '',
        _arr = arr;
    for (var i = 0; i < _arr.length; i++) {
        var one = _arr[i].toString(2),
            v = one.match(/^1+?(?=0)/);
        if (v && one.length == 8) {
            var bytesLength = v[0].length;
            var store = _arr[i].toString(2).slice(7 - bytesLength);
            for (var st = 1; st < bytesLength; st++) {
                if (_arr.length > i + st) {
                    store += _arr[st + i].toString(2).slice(2);
                } else {
                    store = '000000';
                }
            }
            str += String.fromCharCode(parseInt(store, 2));
            i += bytesLength - 1;
        } else {
            str += String.fromCharCode(_arr[i]);
        }
    }
    return str;
}
           
//構建一個檢視,把位元組陣列寫到快取中,索引從0開始,大端位元組序
function getView(bytes) {
    var view = new DataView(new ArrayBuffer(bytes.length));
    for (var i = 0; i < bytes.length; i++) {
        view.setUint8(i, bytes[i]);
    }
    return view;
}

function toString(bytes) {
    //var data = getView(bytes);
    return byteToString(bytes);
}

//對應陣列,或單數結果
function toBytes(bytes) {
    if (bytes.length > 1) {
        return bytes;
    } else {
        return bytes[0];
    }
}
//將位元組陣列轉成有符號的8位整型,大端位元組序
function toInt8(bytes) {
    return getView(bytes).getInt8();
}
//將位元組陣列轉成無符號的8位整型,大端位元組序
function toUint8(bytes) {
    return getView(bytes).getUint8();
}
//將位元組陣列轉成有符號的16位整型,大端位元組序
function toInt16(bytes) {
    return new Int16Array(getView(bytes).buffer, 0, 1)[0]; 
}
//將位元組陣列轉成無符號的16位整型,大端位元組序
function toUint16(bytes) {
    return new Uint16Array(getView(bytes).buffer, 0, 1)[0];
}
//將位元組陣列轉成有符號的32位整型,大端位元組序
function toInt32(bytes) {
    return new Int32Array(getView(bytes).buffer, 0, 1)[0]; 
}
//將位元組陣列轉成無符號的32位整型,大端位元組序
function toUint32(bytes) {
    return new Uint32Array(getView(bytes).buffer, 0, 1)[0]; 
}
//將位元組陣列轉成有符號的64位整型,大端位元組序
function toInt64(bytes) {
    return new BigInt64Array(getView(bytes).buffer, 0, 1)[0];
}
//將位元組陣列轉成有符號的64位整型,大端位元組序
function toUint64(bytes) {
    return new BigUint64Array(getView(bytes).buffer, 0, 1)[0];
}
//將位元組陣列轉成32位浮點型,大端位元組序
function toFloat32(bytes) {
    return getView(bytes).getFloat32();
}
//將位元組陣列轉成64位浮點型,大端位元組序
function toFloat64(bytes) {
    return new Float64Array(getView(bytes).buffer, 0, 1)[0]; 
}
//將數值寫入到檢視中,獲得其位元組陣列,大端位元組序
function getUint8Array(len, setNum) {
    var buffer = new ArrayBuffer(len);  //指定位元組長度
    setNum(new DataView(buffer));  //根據不同的型別呼叫不同的函式來寫入數值
    return new Uint8Array(buffer); //建立一個位元組陣列,從快取中拿取資料
}
//得到一個8位有符號整型的位元組陣列,大端位元組序
function getInt8Bytes(num) {
    return getUint8Array(1, function (view) { view.setInt8(0, num); })
}
//得到一個8位無符號整型的位元組陣列,大端位元組序
function getUint8Bytes(num) {
    return getUint8Array(1, function (view) { view.setUint8(0, num); })
}
//得到一個16位有符號整型的位元組陣列,大端位元組序
function getInt16Bytes(num) {
    return getUint8Array(2, function (view) { view.setInt16(0, num); })
}
//得到一個16位無符號整型的位元組陣列,大端位元組序
function getUint16Bytes(num) {
    return getUint8Array(2, function (view) { view.setUint16(0, num); })
}
//得到一個32位有符號整型的位元組陣列,大端位元組序
function getInt32Bytes(num) {
    return getUint8Array(4, function (view) { view.setInt32(0, num); })
}
//得到一個32位無符號整型的位元組陣列,大端位元組序
function getUint32Bytes(num) {
    return getUint8Array(4, function (view) { view.setUint32(0, num); })
}
//得到一個32位浮點型的位元組陣列,大端位元組序
function getFloat32Bytes(num) {
    return getUint8Array(4, function (view) { view.setFloat32(0, num); })
}
//得到一個64位浮點型的位元組陣列,大端位元組序
function getFloat64Bytes(num) {
    return getUint8Array(8, function (view) { view.setFloat64(0, num); })
}
    

使用步驟

程式碼如下(示例):

ByteToType(INT32_TYPE, [0,1,1,2], 0, 4); //轉換型別 int32,源資料,取值下標,取幾位

總結

提示:以上簡單示例,僅為模板,大家可以有自己更好的思路哦。

相關文章