2013-11-14 58 views
2

我有一些大的base64编码数据(存储在hadoop文件系统中的snappy文件中)。 此数据最初是经过gzip压缩的文本数据。 我需要能够读取此编码数据的块,对其进行解码,然后将其刷新到GZIPOutputStream。Base64数据流解码

关于如何做到这一点,而不是将整个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]; 
    } 
} 

不幸的是,这种方法没有给出任何人类可读的输出。 理想情况下,我想流式读取,解码和流出数据。

现在,我试图把在一个InputStream,然后复制到gzipout

byteBuffer.get(bufferBytes); 

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

,它给了我一个 产生java.io.IOException:腐败GZIP拖车

+0

'byteBuffer.put(Base64.decodeBase64(记录));' 不应认为是'byteBuffer.put(Base64.encodeBase64(记录));' –

+0

的 '记录' 是Base64编码。我试图获取解码数据并将其添加到ByteBuffer。 –

回答

3

走吧一步一步:

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

  2. 您需要一个能够读取Base64编码数据的输入流。我建议从apache-commons-codec得到方便的Base64InputStream。通过构造函数,您可以设置行长度,行分隔符并设置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参数(行长度和行尾字节数组),你可能需要调整它们。

+0

非常感谢Nikos。 Base64InputStream类有所帮助。 –

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。

+0

如果固定长度为76,那么他们不会包含构造函数的参数。还要考虑整个事情是一行的数据URI。 – TWiStErRob