java nio 直接缓冲区上的压缩
gzip 输入/输出流不在 Java 直接缓冲区上运行。
是否有直接在直接缓冲区上运行的压缩算法实现?
这样就不会产生将直接缓冲区复制到 java 字节数组进行压缩的开销。
The gzip input/output stream dont operate on Java direct buffers.
Is there any compression algorithm implementation out there that operates directly on direct buffers?
This way there would be no overhead of copying a direct buffer to a java byte array for compression.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我并不是想转移你的注意力,但这真的是你的程序中一个很好的优化点吗?您是否使用分析器验证过确实存在问题?您提出的问题意味着您没有做过任何研究,而只是猜测您通过分配 byte[] 会遇到性能或内存问题。由于该线程中的所有答案都可能是某种黑客行为,因此您应该在修复问题之前验证您是否确实存在问题。
回到问题,如果您想在 ByteBuffer 上“就地”压缩数据,答案是否定的,Java 中没有内置的功能可以做到这一点。
如果您按如下方式分配缓冲区:
您可以按照前面的答案建议通过 ByteBufferInputStream 过滤您的 byte[] 。
I don't mean to detract from your question, but is this really a good optimization point in your program? Have you verified with a profiler that you indeed have a problem? Your question as stated implies you have not done any research, but are merely guessing that you will have a performance or memory problem by allocating a byte[]. Since all the answers in this thread are likely to be hacks of some sort, you should really verify that you actually have a problem before fixing it.
Back to the question, if you're wanting to compress the data "in place" in on a ByteBuffer, the answer is no, there is no capability to do that built into Java.
If you allocated your buffer like the following:
You can filter your byte[] through a ByteBufferInputStream as the previous answer suggested.
哇老问题,但今天偶然发现了这个。
可能像 zip4j 这样的库可以处理这个问题,但是您可以在没有外部依赖的情况下完成工作从 Java 11 开始:
如果您只对压缩数据感兴趣,您可以这样做:
src 和 dst 都会改变位置,因此您可能必须在 compress 返回后翻转它们。
为了恢复压缩数据:
请注意,两种方法都希望在一次传递中进行(解)压缩,但是,我们可以使用稍微修改的版本来传输它:
示例:
如果您想要完全符合 zip 标准的数据:
其中:
并且:
因此,zip 会产生 10+8 字节的开销。
为了将一个直接缓冲区解压到另一个缓冲区中,您可以将 src 缓冲区包装到一个 InputStream 中:
并使用:
当然,这并不酷,因为我们将数据复制到临时数组,但无论如何,它是一种往返检查这证明基于 nio 的 zip 编码写入了可以从基于标准 io 的消费者读取的有效数据。
因此,如果我们忽略 crc 一致性检查,我们可以删除页眉/页脚:
Wow old question, but stumbled upon this today.
Probably some libs like zip4j can handle this, but you can get the job done with no external dependencies since Java 11:
If you are interested only in compressing data, you can just do:
Both src and dst will change positions, so you might have to flip them after compress returns.
In order to recover compressed data:
Note that both methods expect (de-)compression to happen in a single pass, however, we could use slight modified versions in order to stream it:
Example:
If you want fully zip compliant data:
Where:
And:
So, zip imposes 10+8 bytes of overhead.
In order to unzip a direct buffer into another, you can wrap the src buffer into an InputStream:
and use:
Of course, this is not cool since we are copying data to a temporary array, but nevertheless, it is sort of a roundtrip check that proves that nio-based zip encoding writes valid data that can be read from standard io-based consumers.
So, if we just ignore crc consistency checks we can just drop header/footer:
如果您使用 ByteBuffers,您可以使用一些简单的输入/输出流包装器,例如:
测试:
If you are using ByteBuffers you can use some simple Input/OutputStream wrappers such as these:
Test: