首页 > 解决方案 > Zip ByteArray 解压返回 null 但输入流有效

问题描述

所以我试图在内存中压缩一个csv文件,将它作为一个BLOB存储在MYSQL中,然后获取并解压缩它,但是ZipInputStream.getEntry返回null,我真的无法解压文件,我尝试了一切,我真的可以找不到答案。我第一次使用 GZIP 压缩/解压缩文件并工作,但它改变了 CSV 文件结构,所以这就是我尝试使用 Zip 的原因。CSV 文件是通过 Spring 的 MultipartFile.getBytes() 从前端接收的。

这是从 DB 中看到的压缩文件标头(标头似乎有效)

00000000  50 4B 03 04 14 00 08 08 08 00 B4 A0 8F 50 00 00    PK........´ .P..

提前致谢!

压缩方法:

@Throws(Exception::class)
fun compressFile(file : ByteArray) : ByteArray {
    val baos = ByteArrayOutputStream()
    val zos = ZipOutputStream(baos)
    val entry = ZipEntry("data.csv")
    entry.size = file.size.toLong()
    zos.putNextEntry(entry)
    zos.write(file)
    zos.closeEntry()
    zos.close()
    return baos.toByteArray()
}

解压方式:

@Throws(Exception::class)
fun decompressFile(file : ByteArray): ByteArray {
   if (file.isEmpty()) return file
   val gis = ZipInputStream(ByteArrayInputStream(file))
   val bf = BufferedReader(InputStreamReader(gis, "UTF-8"))
   var outStr = ""
   var line: String
   while (bf.readLine().also { line = it ?: "" } != null) {
       outStr += line
   }
   gis.close()
   bf.close()
   return outStr.toByteArray()
}

初始化后的 ZipInputStream 对象

标签: javafilecsvkotlincompression

解决方案


要阅读 a ZipInputStream,您必须getNextEntry()在阅读前致电。

对于此示例,我创建了一个包含 2 个文件的 zip 文件:

  • foo.text有内容Foo Bar
  • hello.txt有内容Hello World

以下代码显示在调用之前尝试读取getNextEntry()不会产生任何结果:

public static void main(String[] args) throws Exception {
    try (ZipInputStream zip = new ZipInputStream(new FileInputStream("C:\\Temp\\foo.zip"))) {
        BufferedReader reader = new BufferedReader(new InputStreamReader(zip, "UTF-8"));

        // read before getNextEntry() finds nothing
        printText(reader);

        ZipEntry zipEntry;
        while ((zipEntry = zip.getNextEntry()) != null) {
            System.out.println("Entry Name: " + zipEntry.getName() + "   Size: " + zipEntry.getSize());

            // read after getNextEntry() finds only the entry's content
            printText(reader);
        }
    }
}
static void printText(BufferedReader reader) throws IOException {
    int count = 0;
    for (String line; (line = reader.readLine()) != null; count++)
        System.out.println("  " + line);
    System.out.println(count + " lines");
}

输出

0 lines
Entry Name: foo.txt   Size: 7
  Foo Bar
1 lines
Entry Name: hello.txt   Size: 11
  Hello World
1 lines

推荐阅读