- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我目前正在使用 Apache POI 创建一个 Excel 文件。我想通过 multipart upload 将此文件发送到 AWS S3 。我正在使用SXSSFWorkbook结合 BigGridDemo 使用的替换技术为了创建文档本身并发送工作表数据。这就是有点棘手的地方。我的一些东西大部分工作正常,但由于 NUL
被写入组成工作表数据的 XML 文件中,因此生成了无效的 excel 文件。
在试图找出发生这种情况的原因时,我偶然发现了这一点:
import java.io._
import java.util.zip._
val bo = new ByteArrayOutputStream()
val zo = new ZipOutputStream(bo)
zo.putNextEntry(new ZipEntry("1"))
zo.write("hello".getBytes())
zo.write("\nhello".getBytes())
val bytes1 = bo.toByteArray()
// bytes1: Array[Byte] = Array(80, 75, 3, 4, 20, 0, 8, 8, 8, 0, 107, -121, -9, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 49)
bo.reset()
zo.write("hello".getBytes())
val bytes2 = bo.toByteArray() // bytes2: Array[Byte] = Array()
zo.flush()
val bytes2 = bo.toByteArray() // bytes2: Array[Byte] = Array()
bo.size //res11: Int = 0
zo.putNextEntry() // If I make a new entry it works but I can't do this in real code...
bo.size // res17: Int = 66
似乎当我重置底层字节输出流时,它会导致 ZipOutputStream 不再记录任何内容。这让我很惊讶,所以我去查看了underlying source code of ZipOutputStream 。我注意到默认方法是 DEFLATED,它只调用 DeflaterOutputStream#write ,然后我研究了压缩器代码本身,认为压缩算法中可能有一些我不明白的更深层次的东西,要求流不被重置或者以某种方式受到它的影响。我找到了对 FULL_FLUSH 的引用并指出
The compression state is reset so that the inflater that works on the compressed output data can restart from this point if previous compressed data has been damaged or if random access is desired.
这对我来说听起来不错,因为我可以想象重置字节流可能会被视为损坏的数据。所以我重复了我的最小实验:
import java.io._
import java.util.zip._
val bo = new ByteArrayOutputStream()
val zo = new ZipOutputStream(bo)
zo.setLevel(Deflater.FULL_FLUSH)
zo.putNextEntry(new ZipEntry("1"))
zo.write("hello".getBytes())
val bytes1 = bo.toByteArray()
// bytes1: Array[Byte] = Array(80, 75, 3, 4, 20, 0, 8, 8, 8, 0, 84, 75, -8, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 49)
zo.flush()
bo.reset()
zo.write("\nhello".getBytes())
zo.flush()
val bytes2 = bo.toByteArray() // bytes2: Array[Byte] = Array()
所以没有骰子。我的目标是将所有内容保留在内存中(因此是字节数组),并通过删除已经写入 UploadPartRequest 的字节来保持较低的内存压力,但这确实给事情带来了麻烦,因为我的印象是XML 文件必须被压缩,因为 Excel 文件格式实际上是一个 zip 文件。我的完整代码显然有点复杂,并且使用 Play framework和 Scala 2.12.6,I've put it on github here and added some additional comments if you'd like to look at it or run it.
我知道我可以通过先将 Excel 文件写入磁盘然后上传它来完成将此文件部分上传到 s3,但出于我的目的,我希望有一个全内存解决方案,所以我没有处理生成大型临时文件时 Web 服务器上的磁盘空间问题。通过保持生成的行在生成时上传,我认为每次上传的内存压力应该保持相当恒定。以下是当前代码在 xml 文件工作表数据中生成的内容:
...
这对我来说意味着,尽管我的实验没有显示任何字节,但在某些时候会发生更多字节,并会在 NUL 最终结束后写入文件。
那么...为什么会发生这种情况?为什么 ByteArrayOutputStream.reset()
会导致在 ZipOutputStream
上写入时出现问题?如果我不调用 .reset() ,ByteArrayOutputStream
似乎会扩展直至变得巨大并导致内存不足错误?或者我不应该担心,因为数据无论如何都会被压缩?
最佳答案
我不认为这是 ByteArrayOutputStream.reset()
的错.
类似于CipherStreams
和其他过滤器流,DeflaterOutputStream
因此ZipOutputStream
实际上不会写入底层流(您的 ByteArrayOutputStream
),直到它可以/需要(有时甚至在您刷新时)。
我相信在这种情况下 ZipInputStream
它可能只在某些 block 大小上或在 ZipEntry
关闭时写入底层流。 ;不太确定,但这是我的猜测。
示例:
val bo = new ByteArrayOutputStream()
val zo = new ZipOutputStream(bo)
zo.putNextEntry(new ZipEntry("example entry"))
// v prints the entry header bytes v
println(bo.toString())
zo.write("hello".getBytes())
zo.flush();
// v still only the entry header bytes v
println(bo.toString())
我在 ExcelStreamingToS3Service - line 155
中注意到一件事您可能想更改为 zos.write(byteBuffer, offset, offset + bytesRead)
,或类似的东西。写入完整缓冲区肯定可能是导致所有这些的原因 NUL
字符,因为您的缓冲区在读取过程中可能尚未填充,并且仍然有许多空索引。毕竟,看起来 xml 继续从 NUL
之前中断的地方继续。就像这里:<c r="C1 ... 940" t="inlineStr">
所以看起来你确实正在编写所有数据,只是将其与 NUL
散布在一起s。
关于java - 将 Excel 文件流式传输到 S3 内存中?为什么 ZipOutputStream 上的 ByteOutputStream.reset() 会导致写入无法工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51500989/
我可以压缩文件,但内容错误......例如 - a.txt 中的内容: !"#$%&'()*+,-./0123456789:;?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abc
我希望能够通过网络读取多个数据流并将文件写入网络以组合所有这些多个文件。 由于文件可能非常大,我不想做任何本地IO文件操作,而是对数据流进行操作。从网络读取流,将流以 zip 格式写入网络。 我正在尝
我有两个例子: 示例 1: try (ByteArrayOutputStream baous = new ByteArrayOutputStream(); FileOutputStre
我正在使用 ZipOutputStream创建 ZIP 文件。它工作正常,但 Javadoc 非常稀疏,所以我对 ZipOutputStream 的特性有疑问: 支持的最大文件大小是否有限制?对于 Z
我试图通过 ZipOutputStream 输出数据,但生成的文件未压缩。这是在 Windows 7 下。这是一个示例: import java.io.*; import java.nio.file.
我使用 ZipOutputStream 创建 zip 文件。我把一个文件放在zip中(文件和zip都在同一个目录),但是文件是用完整路径存储的(C:\TEMP\file.xml),如何用相对路径或没有
我需要压缩来自一个流的数据并将压缩数据放入另一个流。下面是操作文件的代码(MyOutputStream 是一个用于调试目的的简单 FileOutputStream 包装器)。此代码工作正常。
我有点困惑。我知道空 zip 是不合法的。但是这个示例片段呢: ZipOutputStream zos = null; try { zos = new ZipOutputStream(new
我想使用 java.util.ZipOutputStream 类压缩文本文件。我在互联网上找到了两个示例来解释如何做到这一点。这使我想到了如下所示的两种可能的实现。虽然这两种方法都会生成“健康的 zi
我想创建 zip 文件。文件将包含导出的 Preferences 和 Serialized 对象。但是当我尝试替换 zip 存档中的对象时,保存的首选项消失了。如何解决这个问题? import jav
这个问题不太可能对任何 future 的访客有帮助;它只与一个较小的地理区域、一个特定的时间点或一个非常狭窄的情况相关,通常不适用于全世界的互联网受众。如需帮助使此问题更广泛适用,visit the
我必须上传一个zip文件到ftp服务器,这里的zip文件也是动态构建的。 import java.io.File; import java.io.FileInputStream; import jav
我尝试用 DeflaterOutputStream 压缩一个字符串并用 base64 转换输出以将结果保存在另一个字符串中 public static String compress(String s
我正在使用 Java7 编写代码,并使用 try-with-resources 功能。当我创建 ZipOutputStream 的实例时。通过这样做,我不再需要在finally block 中关闭流。
我正在尝试使用 MockitoJUnitRunner 编写 JUnit。我将文件 ID 传递给我的函数,该函数从云下载文件并返回 zip 文件作为下载。这是我的代码 public void getLo
我的 bean 类中有以下代码块 - HttpServletResponse response = (HttpServletResponse) getFacesContext().getExterna
这真的是一个由两部分组成的问题。 前言:我用WinRAR压缩文件。它为您提供了仅压缩某些文件的选项。我可以按文件扩展名进行过滤,例如,JPEG 文件不会被压缩,而其他文件会被压缩。 这可以用一般的 Z
ZipOutputStream 仅压缩文件夹中的文件。我也想压缩子文件夹。我怎样才能做到这一点? 最佳答案 您必须递归地探索您的目录才能添加 zip 中的所有文件。 如果你愿意,可以看看这个小 hel
我有一个要返回给浏览器的 ZipOutputStream。我想要的体验是用户点击一个 anchor 标签,然后为我有的ZipOutputStream 显示一个文件下载提示。 如何将 ZipOutput
我正在使用此处描述的技术创建一个 zip 文件: http://info.michael-simons.eu/2008/01/21/using-rubyzip-to-create-zip-files-
我是一名优秀的程序员,十分优秀!