5

base64 でエンコードされた大きなデータがいくつかあります (hadoop ファイルシステムのスナップ ファイルに格納されています)。このデータはもともと gzip されたテキスト データでした。このエンコードされたデータのチャンクを読み取り、デコードして、GZIPOutputStream にフラッシュできる必要があります。

base64 データ全体を配列にロードして Base64.decodeBase64(byte[]) を呼び出す代わりに、これを行う方法についてのアイデアはありますか?

「\r\n」区切り文字まで文字を読み取り、1 行ずつデコードすれば正しいでしょうか? 例:

for (int i = 0; i < byteData.length; i++) {
    if (byteData[i] == CARRIAGE_RETURN || byteData[i] == NEWLINE) {
       if (i < byteData.length - 1 && byteData[i + 1] == NEWLINE)
            i += 2;
       else 
            i += 1;

       byteBuffer.put(Base64.decodeBase64(record));

       byteCounter = 0;
       record = new byte[8192];
    } else {
        record[byteCounter++] = byteData[i];
    }
}

残念ながら、このアプローチでは人間が読める出力は得られません。理想的には、データの読み取り、デコード、およびストリーミングをストリーミングしたいと考えています。

今、入力ストリームに入れてから gzipout にコピーしようとしています

byteBuffer.get(bufferBytes);

InputStream inputStream = new ByteArrayInputStream(bufferBytes);
inputStream = new GZIPInputStream(inputStream);
IOUtils.copy(inputStream , gzipOutputStream);

そして、それは私に java.io.IOException: Corrupt GZIP Trailer を与えます

4

2 に答える 2

6

一歩一歩進みましょう:

  1. GZIPInputStream圧縮されたデータを読み取るにはが必要です(GZIPOutputStream出力ストリームはデータの圧縮に使用されます)。このストリームがあれば、圧縮されていない元のバイナリ データを読み取ることができます。これにはInputStream、コンストラクターに が必要です。

  2. Base64 でエンコードされたデータを読み取ることができる入力ストリームが必要です。apache-commons-codecの便利なものをお勧めしBase64InputStreamます。コンストラクターを使用すると、行の長さ、行区切りを設定し、データをデコードするように設定できます。これには、別の入力ストリーム (生の Base64 でエンコードされたデータ) が必要です。doEncode=false

  3. このストリームは、データの取得方法によって異なります。理想的には、データは次のように利用できるはずですInputStream-問題は解決しました。そうでない場合は、ByteArrayInputStream(バイナリの場合)、StringBufferInputStream(文字列の場合) などを使用する必要があります。

おおよそ、このロジックは次のとおりです。

InputStream fromHadoop = ...;                                  // 3rd paragraph
Base64InputStream b64is =                                      // 2nd paragraph
    new Base64InputStream(fromHadoop, false, 80, "\n".getBytes("UTF-8"));
GZIPInputStream zis = new GZIPInputStream(b64is);              // 1st paragraph

Base64InputStream(行の長さと行末のバイト配列)の引数に注意してください。調整が必要になる場合があります。

于 2013-11-14T15:10:11.000 に答える
0

私を正しい方向に向けてくれたNikosに感謝します。具体的には、これは私がしたことです:

private static final byte NEWLINE = (byte) '\n';
private static final byte CARRIAGE_RETURN = (byte) '\r';

byte[] lineSeparators = new byte[] {CARRIAGE_RETURN, NEWLINE};      
Base64InputStream b64is = new Base64InputStream(inputStream, false, 76, lineSeparators);

GZIPInputStream zis = new GZIPInputStream(b64is);

76 は Base64 ラインの長さではありませんか? ただし、80 は試しませんでした。

于 2013-11-15T08:41:28.110 に答える