アーカイブされたバイナリ メッセージを含むファイルがあります。小さなファイルは約 600MB で、約 9000 件のメッセージが含まれています。各メッセージは、私が知っている特定の 4 バイト フラグで始まります。これは、メッセージ ヘッダーの最初の 4 バイトを示します (したがって、キャプチャする必要があります)。メッセージ ヘッダーは、すべてのメッセージで固定サイズです。メッセージ ヘッダーの後には、ヘッダーで識別されるサイズのペイロードが続きます。特定のメッセージ ヘッダーの先頭を見つけたら、ヘッダーの末尾までのバイト数がわかるので、それを使用してメッセージ内のバイト数を抽出し、このアーカイブ ファイルを解析して各メッセージを分離して処理する必要があります。 、4 バイト フラグの最初のバイトから指定されたメッセージ長の最後までのすべてのバイトが含まれていることを確認します。メッセージ間にはさまざまなパディングがあります。
ファイルのサイズが大きいため、ファイルを単一の配列として使用したくありません (すべての場合で可能ではありません)。したがって、私は と のようなものを見ていRandomAccessFile
ますFileInputStream
。ファイルをスキャンして特定のバイト シーケンスを探し、そのシーケンスの最初のバイトから既知の長さまですべてのバイトを取得するのは簡単な作業ではないようです。RandomAccessFile
、特にread(byte[])
andseek()
メソッドは、解決策を実装できるように思われます。
アイデアを与えるために、私の現在の実装にはfindFlag()
、 の開始位置を取ると呼ばれるメソッドが含まれていRandomAccessFile
ます。その位置にシークし、そこから始まる 4 バイトを読み取ります。フラグが見つかった場合は、 を返しますstartPos
。それ以外の場合は、再帰的に自分自身を呼び出し、移動してstartPos + 1
、フラグが見つかるまで繰り返します。データ メッセージの一部として読み取った最後のバイトがわかっているので、そこからシークを開始します。
file.seek(startPos);
byte[] possibleFlag = new byte[4];
file.read(possibleFlag, 0, possibleFlag.length);
if (Arrays.equals(ByteUtils.intToBytes(Message.FLAG), possibleFlag)) {
return startPos;
}
else {
return findFlag(startPos + 1);
}
Java (Java 6 以前) または十分にテストされた外部ライブラリ (Apache ライブラリなど) で何かを見落としていますか? そうでない場合、Java でバイナリ データを処理するためのより良い解決策や、私の問題に特に適したアプローチはありますか?