- 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/
这个问题在这里已经有了答案: Why don't Java's +=, -=, *=, /= compound assignment operators require casting? (11 个
我搜索了很多,但没有一个链接能帮助我解决这个问题。我得到了 ORA-21500: internal error code, arguments: [%s], [%s], [%s], [%s], [%s
我正在做 RegexOne 正则表达式教程,它有一个 question关于编写正则表达式以删除不必要的空格。 教程中提供的解决方案是 We can just skip all the starting
([\s\S]+|\s?) 中 |\s? 的目的或作用是什么?如果没有它,表达式会不会与 ([\s\S]+) 相同? 最佳答案 这不是完全相同的。 ([\s\S]+|\s?) 会匹配空字符串,而 ([
这个正则表达式有一组还是两组? 我正在尝试使用第二组访问 bookTitle 但出现错误: Pattern pattern = Pattern.compile("^\\s*(.*?)\\s+-\\s+
在 C 中给定一个字符串指针 s,下面的迭代会做什么?即它以什么方式遍历字符串? for (++s ; *s; ++s); 最佳答案 for (++s ; *s;++s) 表示 将指针 s 递增到字符
我正在用一个 node.js 应用程序解析一个大列表并有这段代码 sizeCode = dbfr.CN_DESC.split('\s+-\s*|\s*-\s+') 这似乎不起作用,因为它返回了 [ '
我正在编写一个简单的字符串连接程序。 该程序按照我发布的方式运行。但是,我首先使用以下代码编写它来查找字符串的结尾: while (*s++) ; 但是,这个方法并没有奏效。我传递给它的字符串
这个问题已经有答案了: What does (?和aramchand来自Mohandas Karamchand G 因此,在使用这些匹配来分割字符串后,您最终会得到 {"M", "K", "G"} 注
我正在尝试转换 Map到 List使用 lambda。 本质上,我想将键和值与 '=' 连接起来之间。这看起来微不足道,但我找不到如何去做。 例如 Map map = new HashMap<>();
我正在经历 K & R,并且在递增指针时遇到困难。练习 5.3(第 107 页)要求您使用指针编写一个 strcat 函数。 在伪代码中,该函数执行以下操作: 将 2 个字符串作为输入。 找到字符串
在下面的代码中,pS 和 s.pS 在最后一行是否保证相等?也就是说,在语句S s = S();中,是否可以确定不会构造一个临时的S? #include using namespace std; s
演示示例代码: public void ReverseString(char[] s) { for(int i = 0, j = s.Length-1; i < j; i++, j--){
我一直在寻找类似于 .NET examples 中的示例的 PowerShell 脚本.取一个 New-TimeSpan 并显示为 1 天 2 小时 3 分钟 4 秒。排除其零的地方,在需要的地方添加
def func(s): s = s + " is corrected" return s string_list = ["She", "He"] for s in string_li
我是 python 的新手。当我在互联网上搜索 lambda 时。我在 lambda_functions 中找到了这个声明. processFunc = collapse and (lambda s:
我最近开始学习正则表达式,并试图为上面的问题写一个正则表达式。如果限制只放在一个字母上(例如不超过 2 个“b”),这并不困难。 那么答案就是:a* c*(b|ε)a* c*(b|ε)a* c* 但是
当我运行 npm install 时出现以下错误,但我无法修复它。 我试过:npm install -g windows-build-tools 也没有修复这个错误 ERR! configure
有很多有趣的haskell网上可以找到片段。 This post可以在 this (awesome) Stack Overflow question 下找到. The author写道: discou
我知道以下三行代码旨在将字符串提取到$ value中并将其存储在$ header中。但是我不知道$value =~ s/^\s+//;和$value =~ s/\s+$//;之间有什么区别。 $val
我是一名优秀的程序员,十分优秀!