我如何通过SFTP(Jsch)写压缩的字节数组而不进行解压缩?

问题描述 投票:4回答:2

(这是x-post到Jsch邮件列表BTW)。我正在从数据库中读取数据,并将其作为字节[]携带(用于跨中间件组件的传输)。

从那个字节[]我知道如何通过使用GZIPOutputStream类在本地文件系统上创建压缩文件。我想做的就是使用JSch SFTP方法在远程文件系统上创建压缩文件。

我压缩了数据的字节[],并将其作为InputStream传递给JSch库,以便通过SFTP传输到远程文件目录(作为.gz文件)。但是,传送的文件具有意外的EOF,因此无法被'gunzipped'

gunzip:GlobalIssuer.xml.gz:文件意外结束

Reminder我没有传输字节[],它是.gz文件的内容,它是数据库记录的内容

(相对)SSCCE如下:

byte[] content = "Content".getBytes();
// It does work (I promise!) returns a 'gzipped' byte[]
byte[] gzippedContent = gzipContent(content);
ByteArrayInputStream bais = new ByteArrayInputStream(gzippedContent);
channelSftp.put(bais, "Content.txt.gz");

gzipContent方法:

private byte[] gzipContent(byte[] content)
{
    ByteArrayInputStream in = new ByteArrayInputStream(content);

    // Create stream to compress data and write it to the to file.
    GZIPOutputStream gzipOutputStream = null;
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    try
    {
        gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream);
        byte[] buffer = new byte[4096];
        int bytes_read;
        while ((bytes_read = in.read(buffer)) != END_OF_FILE)
        {
            gzipOutputStream.write(buffer, 0, bytes_read);
        }

        // Return the gzipped content
        return byteArrayOutputStream.toByteArray();
    }
    catch (IOException e)
    {   
        // Altered from original to make this a SSCCE
        // Don't write exception handling like this at home!
        System.err.println("Unable to gzip content" + e.getMessage());
        return null;
    }
    /* 
     * Lots of closing streams with exception handling below.
     * I *think* I'm closing off streams in the right order
     * It's not triggering any of the System.err.println calls in any case
     * Of course System.err.println is bad, but this is a SSCCE
     */
    finally
    {
        try 
        {
            if (in != null)
            {
                in.close();
            }
        }
        catch (IOException e)
        {
            System.err.println("Was unable to close the Inputstream for gzipping, be aware of mem leak.");
        }
        try 
        {
            if (byteArrayOutputStream != null)
            {
                byteArrayOutputStream.close();
                if (gzipOutputStream != null)
                {
                    gzipOutputStream.close();
                }
            }
        }
        catch (IOException e)
        {
            System.err.println("Was unable to close the OutputStream(s) for gzipping, be aware of mem leak.");
        }
    }
}

原始内容(“内容”)以字节为单位:

0x750x6E0x630x6F0x6D0x700x720x650x730x730x650x640x430x6F0x6E0x740x650x6E0x74

压缩的内容(“内容”)以字节为单位:

0x1F0x8B0x080x000x000x000x000x000x000x00

或替换地:

1f8b 0800 0000 0000 0000 

使用GZIPOutputStream和FileOutputStream写入本地文件系统的等效gzip压缩内容。

1f8b 0800 0000 0000 0000 2bcd 4bce cf2d  ..........+ÍKÎÏ-
284a 2d2e 4e4d 71ce cf2b 49cd 2b01 00f8  (J-.NMqÎÏ+IÍ+..ø
3987 5f13 0000 00                        9._....

我想我看到了问题。尽管内容已正确压缩,但我尚未创建压缩文件所需的校验和后缀(如果在本地文件系统上执行此操作,则GZIPOutputStream会与FileOutputStream一起使用)。所以基本上我错过了这一点:

2bcd 4bce cf2d  ..........+ÍKÎÏ-
284a 2d2e 4e4d 71ce cf2b 49cd 2b01 00f8  (J-.NMqÎÏ+IÍ+..ø
3987 5f13 0000 00                        9._....

我在Jsch库中看不到能做到这一点的方法-这意味着我认为我缺少一些基本要点。

java gzip sftp jsch
2个回答
8
投票

看来您的问题在于将GZipOutputStream与ByteArrayOutputStream结合使用,而与JSch完全无关。

GZipOutputStream正在使用Deflator(通过其超类DeflatorOutputStream)来进行实际工作。直到您使用其finish()方法(通过流finish()close())说压缩文件完成后,该放缩程序才可以缓冲它认为适当的任何数量的数据。然后,这还将gzip页脚(包括校验和)写入目标输出。

我认为您的问题可以通过在getByteArray级联之后移动close()或在其之前添加finish()来解决。


0
投票

END_OF_FILE值的定义在哪里?

© www.soinside.com 2019 - 2024. All rights reserved.