1

Streaming confuses me - just when I think I'm grasping the idea, my code goes belly up.

I'm attempting to take in a string, gzip compress it, and store it in a PostGreSQL database. THEN I want to get it back out and re-transform it into an output stream. The error happens in my 'get' function when I attempt to read the stream into the GZIPstream. The error is:

java.util.zip.ZipException: Not in GZIP format

Here's the functions used to compress the string then put it into the database:

public Jstruct_FileImportRun setSnapshotXml(String inValue) throws IOException
{
    return setSnapshotXml(new BufferedInputStream(new ByteArrayInputStream(inValue.getBytes())));
}

public Jstruct_FileImportRun setSnapshotXml(BufferedInputStream inValue)
{
    try
    {
        ByteArrayOutputStream compressedBytes = new ByteArrayOutputStream(30000 * 1024);
        GZIPOutputStream gzipStream = new GZIPOutputStream(compressedBytes);

        byte[] transferBuffer = new byte[32 * 1024];
        int readSize;
        while ((readSize = inValue.read(transferBuffer)) != -1)
        {
            gzipStream.write(transferBuffer, 0, readSize);
        }
        inValue.close();
        gzipStream.close();

        getField(SNAPSHOT_XML).setValue(compressedBytes.toByteArray());
    }
    catch (IOException e)
    {
        throw new JstructException(e);
    }

    return this;
}

and here's the code (that throws an error) when I attempt to retrieve it:

public static void getSnapshotXml(Connection inConn, Long inRunId, OutputStream inOutputStream) throws Exception
{
    SQLQuery query = new SQLQuery()
            .addSelect(SNAPSHOT_XML)
            .addFrom(getTable())
            .addWhereClause(FILE_IMPORT_RUN_ID + " = " + inRunId);

    ResultSet rs = null;
    try
    {
        rs = query.execute(inConn);
        if (rs.next())
        {
            InputStream stream = rs.getBinaryStream(SNAPSHOT_XML.name());
            GZIPInputStream gzipStream = new GZIPInputStream(stream);

            byte[] transferBuffer = new byte[32 * 1024];
            int readSize;
            while ((readSize = gzipStream.read(transferBuffer)) != -1)
            {
                inOutputStream.write(transferBuffer, 0, readSize);
            }

            gzipStream.close();
            inOutputStream.close();
        }
    }
    finally
    {
        SQLUtil.closeResultSetAndStatement(rs);
    }

}

again, the error "java.util.zip.ZipException: Not in GZIP format" happens in the line "GZIPInputStream gzipStream = new GZIPInputStream(stream);"

Halp!! what am I doing wrong?

russellelbert
  • 643
  • 4
  • 9
  • 23
  • Can you look at the values in the database with something like `psql` an confirm that they're what you think they are? Also, try printing the contents of `rs.getBinaryStream(SNAPSHOT_XML.name())` and see if it's what you expect. Basically, ignore gzip for now (the Java implementation works), and focus on making sure you're storing and retrieving correctly. – David Ehrmann Nov 20 '15 at 18:49
  • Thank you for your response - It appears to be storing some representation of the data in the database after the set function - it's a compressed XML string and there is a value in the field (that looks nothing like the original!). Doing a println on the rs.getBina... gives me this: **java.io.ByteArrayInputStream@74294adb** – russellelbert Nov 20 '15 at 18:57
  • You need to actually read the data; toString on ByteArrayInputStream isn't helpful. With the gziped data, you can tell if it's gziped in the DB by looking at the header. gziped data starts with something like `H4sICF` in base64. – David Ehrmann Nov 20 '15 at 19:02

0 Answers0