Base64数据流的解码

6
我有一些大的base64编码数据(存储在Hadoop文件系统中的snappy文件中)。 这些数据最初是经过gzip压缩的文本数据。 我需要能够读取这些编码数据的块,解码它,然后将其刷新到GZIPOutputStream中。
你有什么想法可以替代将整个base64数据加载到数组中并调用Base64.decodeBase64(byte[])吗?
如果我读取字符直到'\r\n'分隔符,并逐行解码,我的想法是否正确? 例如:
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异常:GZIP压缩文件尾部损坏


难道不应该是byteBuffer.put(Base64.encodeBase64(record));吗? - Leon Hooijer
“record”是Base64编码的。我正在尝试获取解码后的数据并将其添加到ByteBuffer中。 - James Isaac
2个回答

7

让我们逐步进行:

  1. 你需要一个GZIPInputStream来读取压缩的数据(而不是GZIPOutputStream,输出流用于压缩数据)。有了这个流,你就能够读取未压缩的原始二进制数据。在构造函数中需要传入一个InputStream

  2. 你需要一种能够读取Base64编码数据的输入流。我建议使用方便的Base64InputStream,它来自于apache-commons-codec。你可以通过构造函数设置行长、行分隔符,并将doEncode=false设置为解码数据。这又需要另一个输入流——原始的、Base64编码的数据。

  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 的参数(行长度和结束行字节数组),您可能需要调整它们。

非常感谢,Nikos。Base64InputStream类很有帮助。 - James Isaac

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。


如果长度固定为76,那么他们就不会包含构造函数参数。还要考虑数据URI,其中整个内容都在一行中。 - TWiStErRob

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接