3

それぞれが 1 つのレコードを表す一連のバイト配列を返すバイト ストリームがあります。

ストリームを個々のバイト [] のリストに解析したいと思います。現在、各レコードの終わりを識別できるように 3 バイトの区切り文字をハッキングしていますが、懸念があります。

標準の Ascii レコード区切り文字があることがわかりました。

30  036 1E  00011110    RS        Record Separator

バイト配列 (UTF-8 でエンコードされた) が圧縮および/または暗号化されている場合、この文字から派生した byte[] を区切り文字として使用しても安全ですか? 私の懸念は、暗号化/圧縮出力が他の目的でレコードセパレーターを生成する可能性があることです。ストリーム全体ではなく、個々の byte[] レコードが圧縮/暗号化されることに注意してください。

私はJava 8で作業しており、圧縮にSnappyを使用しています。私はまだ暗号化ライブラリを選択していませんが、確かに強力で標準的な秘密鍵アプローチの 1 つです。

4

2 に答える 2

8

ランダムな非構造化データ (圧縮/暗号化されたデータは非常によく似ています) を扱っている場合、バイトを単純に区切り文字として宣言することはできません。これは、区切り文字がそのようなデータでは常に通常のデータ バイトとして表示される可能性があるためです。

書き込みを開始するときにデータのサイズが既にわかっている場合は、通常、最初にサイズを書き、次にデータを書きます。読み返すと、最初にサイズ (たとえば、int の場合は 4 バイト) を読み取り、次にサイズが示すバイト数を読み取る必要があることがわかります。

書き込み中にサイズがわからない場合、これは明らかに機能しません。その場合、エスケープ メカニズムを使用できます。たとえば、めったに出現しないバイトをエスケープ文字として選択し、データ内でそのバイトが出現するすべてをエスケープし、別のバイトを終了インジケータとして使用します。

例えば

final static byte ESCAPE = (byte) 0xBC;
final static byte EOF = (byte) 0x00;

OutputStream out = ...
for (byte b : source) {
    if (b == ESCAPE) {
        // escape data bytes that have the value of ESCAPE
        out.write(ESCAPE);
        out.write(ESCAPE);
     } else {
        out.write(b);
     }
}
// write EOF marker ESCAPE, EOF
out.write(ESCAPE);
out.write(EOF);

ESCAPE バイトを読み取るときに、次のバイトを読み取って EOF をチェックします。EOF でない場合は、データ バイトを表すエスケープされた ESCAPE です。

InputStream in = ...
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
while ((int b = in.read()) != -1) {
    if (b == ESCAPE) {
        b = in.read();
        if (b == EOF)
            break;
        buffer.write(b);
    } else {
         buffer.write(b);
    }
}

書き込まれるバイトが完全にランダムに分散されている場合、これによりストリームの長さが 1/256 増加します。完全にランダムではないデータ ドメインの場合、出現頻度が最も低いバイトを選択できます (静的データ分析または知識に基づいた推測による)。 .

編集: より複雑なロジックを使用することで、エスケープのオーバーヘッドを減らすことができます。たとえば、この例では、ESCAPE + ESCAPE または ESCAPE + EOF しか作成できません。この例では、残りの 254 バイトは ESCAPE の後に続くことはできないため、正当なデータの組み合わせを格納するために悪用される可能性があります。

于 2015-08-14T17:16:56.080 に答える
2

これは完全に安全ではなく、データに何が現れるかわかりません。おそらく、protobuf のようなもの、または「最初にレコード長を書き込み、次にレコードを書き込み、次にすすぎ、泡立て、繰り返し」のようなスキームを検討する必要がありますか?

長さがある場合は、区切り記号は必要ありません。読み取り側は長さを読み取り、最初のレコードの読み取り量を認識し、次の長さを読み取ることを認識します。すべて、長さ自体が固定長であると想定しています。

protobufs のシーケンスをストリーミングするための開発者の提案を参照してください。

于 2015-08-14T16:34:27.590 に答える