バイナリデータとビット単位の状態を管理する



ビット単位のOP、それは何ですか?

A bitwise operation that operates on a bit string, a bit array, or a binary numeral at the level of individual bits - Wikipedia



なぜバイナリの状態を保存?
シリアル化されたバイナリ形式のデータのエンコードは、文字列形式よりも効率的です.だからこそ、GOBやProtobufsのようなデータエンコーダはJSON & XMLよりも効率的です.
データを保存するために必要なスペースの量を減らします.彼らはフィールド名や空白のようなスペースを取る余分なゴミを含んでいない.
状態を保存したり、バイナリ形式でデータをシリアル化するという欠点は、厳格さです.彼らは厳密な形式に従っているので、両方のエンコーダ&デコーダは、データ形式に新しい変更を処理する方法を更新する必要があります.
さあ、私たちにはposition つのタイプint 8フィールド(半径、経度、および緯度)のみを持つ.バイナリ形式のフィールドを{toBinary(rad)}{toBinary(lat)}{toBinary(long)}If the radius 30(11110)latitude は20(10100)でありlongitude 50(110010)私たちのシリアル化されたバイナリ形式で保存
{toBinary(30)}{toBinary(20)}{toBinary(50)} = {00011110}{00010100}{00110010} = 000111100001010000110010
それは16進数で表される
1e1432
JSONでこれを保存するならば
{"rad":30,"lat":20, "long": 50}
JSON形式はバイナリ形式より多くのメモリを受け取り、フィールド名のスペースを必要としますが、バイナリ形式では、フィールドがバイトの位置に基づいてどこに属しているかわかります.これは二値の状態を記憶する空間効率を示した.
私たちがもはや位置オブジェクトで半径フィールドを必要としないと言いましょう.
JSON形式を使用した場合、radiusフィールドを削除するとエンコードとデコード規則には影響しません.
我々が以前からバイナリ直列化された形式を使用するならば、我々はエンコーダとデコーダが半径分野への変化を意識していることを確認しなければなりません.
ときに{toBinary(rad)}{toBinary(lat)}{toBinary(long)} うん、もう一つは{toBinary(lat)}{toBinary(long)} 注意*フィールドのVaulesとデータの不一致が正確にエンコード/デコードされません.
エンコーダとデコーダが同期していないならば、我々は最初のバイトとして0を通過しなければなりません.これを行うと、以前の位置オブジェクトの書式を保持し、最新の状態で無視できます.

簡易ユースケース
我々は、グループやメディア(SMS、メール、プッシュ)のグループ通知を通知サービスがあります.
この通知サービスは、預金と引き出しの2つの通知の種類があります.
{
    "deposit": {
        "push": {
            "state": true,
            "can_edit": true
        },
        "email": {
            "state": true,
            "can_edit": false
        },
        "sms": {
            "state": true,
            "can_edit": false
        }
    },
    "withdrawal": {
        "push": {
            "state": true,
            "can_edit": true
        },
        "email": {
            "state": true,
            "can_edit": false
        }
    }
}
ですから、JSONオブジェクトをバイナリシリアル化形式で保存する方法を考え出すことです.このようなもの0001011100000111
JSONから行く→バイナリ
バイナリは0と1だけで構成され、これはブール値を表すことができます.バイナリのあらゆるビット位置は2の力です.そして、ちょうど10進の各々の位置が10(1 , 10100)の力であるように.
上記のJSON表現をバイナリにフォーマットするには、まず通知カテゴリの内容を平らにします.
{
  "deposit": {
    "push_state": true,
    "push_can_edit": true,
    "email_state": true,
    "email_can_edit": false,
    "sms_state": true,
    "sms_can_edit": false
  },
  "withdrawal": {
    "push_state": true,
    "push_can_edit": true,
    "email_state": true,
    "email_can_edit": false,
    "sms_state": false, //false cus it's empty
    "sms_can_edit": false//false cus it's empty
  }
}
それが平らになったので、我々はバイトで各々のフィールドを代表したいです.バイトが個々のビットとしてフィールドを表すことができるように、バイトは8ビットでできています.
フィールドタイプはBOOLですので1 表すtrue and 0 表すfalse .
そこでフィールドをビット位置にマップします.
push_state => 1st bit
push_can_edit => 2nd bit
email_state => 3rd bit
email_can_edit => 4th bit
sms_state => 5th bit
sms_can_edit => 6th bit
現在の通知設定を表すことができます
{
  "deposit": "00010111",
  "withdrawal": "00000111"
}
上記のJSONをバイト単位で変更したい([]バイト).これを行うには、通知カテゴリのバイト配列にインデックス位置を設定する必要があります.
長さ2(2つの通知カテゴリー)の私たちのバイト配列のために.deposit_vaue 配列内の1番目の値となりますwithdrawal_value 二番目.
[]byte{deposit_value,withdrawal_value}
[]byte{0b00010111,0b00000111} = 0001011100000111 = 0x1707
今、我々は最終的に我々の通知設定を表すことができます
0001011100000111 #binary format
1707 #hexidecimal format
[]byte{23,7} #in code

set , unset & check演算子
通知設定オブジェクトを保存するためにバイナリシリアル化形式を持っているので、次のステップは通知設定のバイナリ表現を更新します.それを電話しましょうbitNotifcationSetting .
私たちはセットを使用し、unset&ビット演算子をチェックしてビットのビットを操作するbitNotifcationSetting .
セット演算子:これを1秒に設定する.
set_op(data, nth_flag) => data | nth_flag
Unset演算子:このとき、n番目のビットを0に設定します.
unset_op(data, nth_flag) => data & ^(nth_flag)
チェックビット演算子:これをチェックします.
check_bit_op(data, nth_flag) => (data & (nth_flag) != 0
golang playground example

通知媒体状態の更新
SMS状態を更新したいとしましょう.
  • カテゴリのインデックスを使用して編集するバイトを選択します.

  • チェックサムBittleオペ(*) to c*heck if the ` ssSum状態`ビットは編集可能です.
  • 注意してください.
  • 呼び出しset_op(bitNotifcationSetting, sms_state_flag) 設定するsms_state ビットを1/trueまたは呼び出しunset_op(bitNotifcationSetting, sms_state_flag) セットsms_state ビットを0にする
  • 上記の手順に従って、演算子がビットの操作でどのように使用されるかを確認します.

    結論
    ここで使用されるバイナリ形式は、使用されるメモリスペースを減らすのを助けることができて、キャッシュをより多くの最近の値に対応するためにクリーンアップする必要なしで、メモの通知設定についてのさらなる情報を保持することができます.
    ここで使用している例は、フィールドタイプがBooleanで、ビットを取るので簡単です.可変長の文字列と型のようなより複雑な型に対して、バイナリ形式を使用すると、外部ライブラリの助けなしで自分で管理するのは少し難しいでしょう.
    もっと複雑な方法でBitcoin encodes transaction バイナリ形式へのオブジェクト.

    続きを読む
  • ビットコインのトランザクションとブロックをエンコードする方法を見てください
  • いくつかのMongoDBビットごとのクエリ演算子を調べます.bindataを使用するとき、ドキュメントを問い合わせるのを助けることができました