从输入流中解压文件的方法

8

我正在尝试从服务器获取一个zip文件。使用 HttpURLConnection 获取 InputStream,这是我的代码:

myInputStream.toString().getBytes().toString()  is equal to [B@4.....

byte[] bytes = Base64.decode(myInputStream.toString(), Base64.DEFAULT);
String string = new String(bytes, "UTF-8");
string == �&ܢ��z�m����y....

我真的尝试解压这个文件,但是没有任何作用,还有很多问题,我应该使用GZIPInputStream还是ZipInputStream?我必须将此流保存为文件,还是可以在InputStream上工作?
请帮忙,我的老板变得不耐烦了:O 我不知道这个文件里面有什么,我必须找出来:)

1
请点击这里进行下载。 - seenukarthi
将此 zip 文件写入 sdcard,然后尝试解压缩。不要忘记授予读写权限。 - AmniX
使用 inputStream.toString() 肯定不会做你想要的事情。就像 java.io.File.toString() 不会将文件的内容打印为字符串,而是其他东西(文件的路径),如果你对内容感兴趣,这是无用的。 - GPI
3个回答

0
GZipInputStream和ZipInputStream是两种不同的格式。https://en.wikipedia.org/wiki/Gzip 直接从流中检索字符串并不是一个好主意。您可以从InputStream创建一个File,并使用FileOutputStream将数据写入其中。
在Base 64中进行解码是另一回事。如果您的流已经在上游解码了该格式,则可以;否则,您必须使用另一个输入流来封装您的流,以解码Base64格式。 最佳实践是使用缓冲区以避免内存溢出。
这里有一些Kotlin代码,用于解压缩InputStream压缩到文件中。(比Java更简单,因为byte []的管理很繁琐):
val fileBinaryDecompress = File(..path..)
val outputStream = FileOutputStream(fileBinaryDecompress)

readFromStream(ZipInputStream(myInputStream), BUFFER_SIZE_BYTES,
    object : ReadBytes {
         override fun read(buffer: ByteArray) {
             outputStream.write(buffer)
         }
    })
outputStream.close()

interface ReadBytes {
    /**
     * Called after each buffer fill
     * @param buffer filled
     */
    @Throws(IOException::class)
    fun read(buffer: ByteArray)
}

@Throws(IOException::class)
fun readFromStream(inputStream: InputStream, bufferSize: Int, readBytes: ReadBytes) {
    val buffer = ByteArray(bufferSize)
    var read = 0
    while (read != -1) {
        read = inputStream.read(buffer, 0, buffer.size)
        if (read != -1) {
            val optimizedBuffer: ByteArray = if (buffer.size == read) {
                buffer
            } else {
                buffer.copyOf(read)
            }
            readBytes.read(optimizedBuffer)
        }
    }
}

如果您想从服务器获取文件而不解压缩它,请删除ZipInputStream()装饰器。

-1
通常情况下,GZIPInputStream或ZipInputStream之间没有明显的区别,所以如果有的话,两者都应该可以工作。
接下来,您需要确定压缩流是否经过Base64编码,或者某些Base64编码内容是否被放入了压缩流中 - 根据您在问题中提供的信息,似乎是后者选项。
因此,您应该尝试:
ZipInputStream zis = new ZipInputStream( myInputStream );
ZipEntry ze = zis.getNextEntry();
InputStream is = zis.getInputStream( ze );

并从那里开始...


垃圾。一个是流压缩方法:另一个是用于压缩文件集的系统。 - user207421
@EJP:即使声明某些东西是垃圾,也请使用正确的措辞:ONE是一种流压缩方法(GZIPInputStream),另一种是用于压缩文件集的方法(ZipInputStream)。 如果能提供更多关于为什么答案应该是垃圾的细节,那就更好了。当你知道得更多时,为什么没有回答这个问题呢? - tquadrat

-1

基本上,通过将inputStream设置为GZIPInputStream,应该能够读取实际内容。 另外,为了简化操作,使用apache.commons中的IOUtils包可以让您的生活更轻松。

这对我很有效:

    InputStream is ; //initialize you IS
    is = new GZIPInputStream(is);
    byte[] bytes = IOUtils.toByteArray(is);
    String s = new String(bytes);
    System.out.println(s);

1
虽然这段代码可能解决了提问者的问题,但是加上一些解释对于未来的读者会更有帮助。 - Thom
1
@TheThom,是的,你说得对,抱歉我在发布帖子时有点忙。我已经编辑了我的帖子。 - nafas

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