0

Byte ArrayJava コードを使用して Cassandra に値を書き込む必要があります。次に、Cassandra からそのバイト配列データを取得し、デシリアライズする C++ プログラムを作成します。

Cassandra に書き込むバイト配列は、以下で説明する 3 つのバイト配列で構成されています。

short employeeId = 32767;
long lastModifiedDate = "1379811105109L";
byte[] attributeValue = os.toByteArray();

ここで、と を一緒に 1 つのバイト配列に書き込みemployeeId、その結果のバイト配列を Cassandra に書き込みます。次に、そのバイト配列データを Cassandra から取得し、デシリアライズして を抽出する C++ プログラムを作成します。それ。lastModifiedDateattributeValueemployeeIdlastModifiedDateattributeValue

Cassandra への書き込み中に Java コードでビッグ エンディアンを使用して、読み戻し中に C++ コードを簡略化する必要があるかどうかわかりません。

Java側で、すべてを単一のバイト配列に書き込みながら特定の形式(ビッグエンディアン)に従っていることを確認しました。その後、このバイト配列もCassandraに書き戻されますが、これが正しいかどうかはわかりませんいいえ?

public static void main(String[] args) throws Exception {

    String os = "Byte Array Test";
    byte[] attributeValue = os.getBytes();

    long lastModifiedDate = 1379811105109L;
    short employeeId = 32767;

    ByteArrayOutputStream byteOsTest = new ByteArrayOutputStream();
    DataOutputStream outTest = new DataOutputStream(byteOsTest);

    // merging everything into one Byte Array here
    outTest.writeShort(employeeId);
    outTest.writeLong(lastModifiedDate);
    outTest.writeInt(attributeValue.length);
    outTest.write(attributeValue);

    byte[] allWrittenBytesTest = byteOsTest.toByteArray();

    // initially I was writing allWrittenBytesTest into Cassandra...

    ByteBuffer bb = ByteBuffer.wrap(allWrittenBytesTest).order(ByteOrder.BIG_ENDIAN);

    // now what value I should write into Cassandra?
    // or does this even looks right?

    // And now how to deserialize it?

}

ここでこのByteBufferのことを手伝ってくれる人はいますか? ありがとう..

Byte Buffer を使用するのはこれが初めてであるため、ここで Byte Buffer に関する詳細が欠落している可能性があります..

  1. まず、私のユース ケースでは、ここで ByteByffer を使用する必要がありますか?
  2. 第二に、もしそうなら、私のユースケース内でそれを使用する最良の方法は何ですか...?

私が確認しようとしている唯一のことは、ビッグエンディアンのバイトオーダー形式に従ってCassandraに正しく書き込んでいるため、C++側では、そのバイト配列を逆シリアル化しているときにまったく問題に直面していないということです...

4

3 に答える 3

3

Thrift の ByteBuffers を手動でシリアル化する代わりに、Cassandra のネイティブ CQL ドライバーを使用します: http://github.com/datastax/java-driver

于 2013-10-02T17:06:21.407 に答える
1

バイト配列のエンディネスはまったく意味がありません。そのため、casandra がデータを解釈しようとしない場合は、ビッグ/リトル エンディアンのどちらでも使用できます。したがって、エンコーディングはマルチバイト値に対してのみ意味があります。

異なるクライアントで、おそらく異なるプラットフォームでデータを使用する場合は、何らかの合意を取り (たとえば BIG エンディアンを使用)、すべてのクライアントで同じエンディネスを使用することをお勧めします。たとえば、Java クライアント コードは次のようになります。

ByteBuffer bb = ByteBuffer.allocate(attributeValue.length + 14).order(ByteOrder.BIG_ENDIAN);
    bb.putShort(employeeId);
    bb.putLong(lastModifiedDate);
    bb.putInt(attributeValue.length);
    bb.put(attributeValue);

ByteBuffer を必要とする API を使用する場合は、ByteBuffer を使用する必要があります。たとえば、NIO チャネルは ByteBuffer で動作するため、SocketChannel を使用して接続する場合は、ByteBuffer を使用できます。マルチバイト値を正しくフォーマットするために ByteBuffer を使用することもできます。たとえば、上記のコードでは、バッファからバイト配列を取得し、最初の 3 つのフィールドがビッグエンディアン表記を使用してパックされたソケットを介して送信できます。

sendByteArray(bb.array());
...
于 2013-10-01T22:27:15.143 に答える
1

まずcassandraは使ったことがないので、ByteBufferの部分についてだけお答えします。

バイトを送信する前に、最初にすべてを bytebuffer に入れる必要があります。そうしないと、保存するもののエンディアンを制御できません。それがまさに ByteBuffer を使用するポイントです。

バイトを送信するには、次を使用します。

int size = 2 + 8 + 4 + attributeValue.length; // short is 2 bytes, long 8 and int 4

ByteBuffer bbuf = ByteBuffer.allocate(size); 
bbuf.order(ByteOrder.BIG_ENDIAN);

bbuf.putShort(employeeId);
bbuf.putLong(lastModifiedDate);
bbuf.putInt(attributeValue.length);
bbuf.put(attributeValue);

bbuf.rewind();

// this is a bad approach because if you modify the returned array
// you are directly modifying the ByteBuffer's internal array.
byte[] bytesToStore = bbuf.array();

// best approach is copy the internal buffer
byte[] bytesToStore = new byte[size];
bbuf.get(bytesToStore);

bytesToStore を保存して、cassandra に送信できるようになりました。

それらを読み返すには:

byte[] allWrittenBytesTest = magicFunctionToAcquireDataFromCassandra();

ByteBuffer bb = ByteBuffer.wrap(allWrittenBytesTest);
bb.order(ByteOrder.BIG_ENDIAN);
bb.rewind();

int size = allWrittenBytesTest.length - 14;
short employeeId = bb.getShort();
long lastModifiedDate = bb.getLong();
int attributeValueLen = bb.getInt();
byte[] attributeValue = new byte[size];
bb.get(attributeValue); // read attributeValue from the remaining buffer

長さは、allWrittenBytesTest.length から 14 を引くことによって再度決定できるため、attributeValue の長さを格納する必要さえありません (14 は、他のフィールドのサイズの合計 [2 + 4 + 8])。

コードを編集しましたが、いくつかのタイプミスがありました。

于 2013-10-01T22:31:18.557 に答える