是否有一个隐藏在Internet中的ByteBuffers方面的gzip放气库?允许我们推送原始数据然后提取放气数据的东西?我们已经搜索过了,但只找到了处理InputStreams和OutputStreams的库。
我们的任务是创建gzip过滤器,用于在管道架构中减少字节缓冲流。这是一个pull架构,其中最后一个元素从早期元素中提取数据。我们的gzip过滤器处理字节缓冲流,没有单个流对象可用。
我们曾尝试将数据流调整为某种InputStream,然后使用GZipOutputStream来满足我们的要求,但至少可以说适配器代码的数量很烦人。
接受后编辑:郑重声明,我们的架构类似于GStreamer等。
处理ByteBuffers并不难。请参阅下面的示例代码。您需要知道缓冲区是如何创建的。选项是:
必须按顺序处理GZIP生成的数据。ByteBuffers必须按照其生成的相同顺序进行处理。
示例代码:
package stack;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.Pipe;
import java.nio.channels.SelectableChannel;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.zip.GZIPInputStream;
public class BufferDeflate {
static AtomicInteger idSrc = new AtomicInteger(1);
/** Queue for transferring buffers */
final BlockingQueue<ByteBuffer> buffers = new LinkedBlockingQueue<ByteBuffer>();
/** The entry point for deflated buffers */
final Pipe.SinkChannel bufSink;
/** The source for the inflater */
final Pipe.SourceChannel infSource;
/** The destination for the inflater */
final Pipe.SinkChannel infSink;
/** The source for the outside world */
public final SelectableChannel source;
class Relayer extends Thread {
public Relayer(int id) {
super("BufferRelayer" + id);
}
public void run() {
try {
while( true ) {
ByteBuffer buf = buffers.take();
if( buf != null ) {
bufSink.write(buf);
} else {
bufSink.close();
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Inflater extends Thread {
public Inflater(int id) {
super("BufferInflater" + id);
}
public void run() {
try {
InputStream in = Channels.newInputStream(infSource);
GZIPInputStream gzip = new GZIPInputStream(in);
OutputStream out = Channels.newOutputStream(infSink);
int ch;
while( (ch = gzip.read()) != -1 ) {
out.write(ch);
}
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* New buffer inflater
*/
public BufferDeflate() throws IOException {
Pipe pipe = Pipe.open();
bufSink = pipe.sink();
infSource = pipe.source();
pipe = Pipe.open();
infSink = pipe.sink();
source = pipe.source().configureBlocking(false);
int id = idSrc.incrementAndGet();
Thread thread = new Relayer(id);
thread.setDaemon(true);
thread.start();
thread = new Inflater(id);
thread.setDaemon(true);
thread.start();
}
/**
* Add the buffer to the stream. A null buffer closes the stream
*
* @param buf
* the buffer to add
* @throws IOException
*/
public void add(ByteBuffer buf) throws IOException {
buffers.offer(buf);
}
}
只需将缓冲区传递给add
方法并从公共source
通道读取。处理给定字节数后可以从GZIP读取的数据量是无法预测的。因此,我使source
通道非阻塞,以便您可以在添加字节缓冲区的同一线程中安全地从中读取。
马克·阿德勒提出了这种方法,这比我最初的回答要好得多,这要归功于他。
package stack;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.zip.CRC32;
import java.util.zip.Deflater;
public class BufferDeflate2 {
/** The standard 10 byte GZIP header */
private static final byte[] GZIP_HEADER = new byte[] { 0x1f, (byte) 0x8b,
Deflater.DEFLATED, 0, 0, 0, 0, 0, 0, 0 };
/** CRC-32 of uncompressed data. */
private final CRC32 crc = new CRC32();
/** Deflater to deflate data */
private final Deflater deflater = new Deflater(Deflater.BEST_COMPRESSION,
true);
/** Output buffer building area */
private final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
/** Internal transfer space */
private final byte[] transfer = new byte[1000];
/** The flush mode to use at the end of each buffer */
private final int flushMode;
/**
* New buffer deflater
*
* @param syncFlush
* if true, all data in buffer can be immediately decompressed
* from output buffer
*/
public BufferDeflate2(boolean syncFlush) {
flushMode = syncFlush ? Deflater.SYNC_FLUSH : Deflater.NO_FLUSH;
buffer.write(GZIP_HEADER, 0, GZIP_HEADER.length);
}
/**
* Deflate the buffer
*
* @param in
* the buffer to deflate
* @return deflated representation of the buffer
*/
public ByteBuffer deflate(ByteBuffer in) {
// convert buffer to bytes
byte[] inBytes;
int off = in.position();
int len = in.remaining();
if( in.hasArray() ) {
inBytes = in.array();
} else {
off = 0;
inBytes = new byte[len];
in.get(inBytes);
}
// update CRC and deflater
crc.update(inBytes, off, len);
deflater.setInput(inBytes, off, len);
while( !deflater.needsInput() ) {
int r = deflater.deflate(transfer, 0, transfer.length, flushMode);
buffer.write(transfer, 0, r);
}
byte[] outBytes = buffer.toByteArray();
buffer.reset();
return ByteBuffer.wrap(outBytes);
}
/**
* Write the final buffer. This writes any remaining compressed data and the GZIP trailer.
* @return the final buffer
*/
public ByteBuffer doFinal() {
// finish deflating
deflater.finish();
// write all remaining data
int r;
do {
r = deflater.deflate(transfer, 0, transfer.length,
Deflater.FULL_FLUSH);
buffer.write(transfer, 0, r);
} while( r == transfer.length );
// write GZIP trailer
writeInt((int) crc.getValue());
writeInt((int) deflater.getBytesRead());
// reset deflater
deflater.reset();
// final output
byte[] outBytes = buffer.toByteArray();
buffer.reset();
return ByteBuffer.wrap(outBytes);
}
/**
* Write a 32 bit value in little-endian order
*
* @param v
* the value to write
*/
private void writeInt(int v) {
System.out.println("v="+v);
buffer.write(v & 0xff);
buffer.write((v >> 8) & 0xff);
buffer.write((v >> 16) & 0xff);
buffer.write((v >> 24) & 0xff);
}
/**
* For testing. Pass in the name of a file to GZIP compress
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
File inFile = new File(args[0]);
File outFile = new File(args[0]+".test.gz");
FileChannel inChan = (new FileInputStream(inFile)).getChannel();
FileChannel outChan = (new FileOutputStream(outFile)).getChannel();
BufferDeflate2 def = new BufferDeflate2(false);
ByteBuffer buf = ByteBuffer.allocate(500);
while( true ) {
buf.clear();
int r = inChan.read(buf);
if( r==-1 ) break;
buf.flip();
ByteBuffer compBuf = def.deflate(buf);
outChan.write(compBuf);
}
ByteBuffer compBuf = def.doFinal();
outChan.write(compBuf);
inChan.close();
outChan.close();
}
}
我不理解“隐藏在互联网中”部分,但zlib在内存中进行gzip格式的压缩和解压缩。java。util。zip API提供了对zlib的一些访问,尽管它是有限的。由于接口限制,您无法请求zlib直接生成和使用gzip流。但是,您可以使用nowrap选项来生成和使用原始的deflate数据。然后,使用java中的CRC32类,很容易滚动您自己的gzip头和尾文件。util。邮政编码。您可以预先设置一个固定的10字节头,附加四字节CRC,然后是四字节未压缩长度(模232),这两者都是以小端顺序进行的,很好。
在尝试为Android使用新的时发生崩溃,并希望分享我的解决方案。 在android appcompat库中尝试新的TextInputField会使我的应用程序崩溃。这是我的布局xml。 我的错误是: 解决方案:将属性添加到,使lead标签如下所示:
我正在尝试嵌入浮动操作按钮。下面是我的xml文件 问题是Im会收到以下错误消息, Android.View.InflateException:二进制XML文件行#300:在Android.View.LayoutInflater.CreateView(LayoutInflater.CreateViewFromTag(LayoutInflater.java:702)在Android.View.Layo
我需要用Java中的Bouncy Castle创建一个自签名X509证书,但我尝试包含的每个类都不推荐使用。我该怎么解决这个问题?还有其他课程吗?谢谢
问题内容: 任何人都可以向我展示(或提供指向)如何使用充气城堡在Java中加密文件的示例吗?我查看了bouncycastle.org,但找不到其API的任何文档。即使只是知道要使用哪些类,也对我入门很有帮助! 问题答案: 您要执行哪种类型的加密?基于密码(PBE),对称,不对称?这就是您配置Cipher的全部方法。 您不必使用任何BouncyCastle特定的API,只需使用它提供的算法即可。这是
问题内容: 应该使用哪种 InputStream 类型来处理将HTTP Content-Encoding 设置为 deflate的 URLConnection流? 对于gzip或zip的Content-Encoding,我使用GZIPInputStream,没问题。 对于“ deflate”的内容编码,我尝试使用 InflaterInputStream 和 DeflaterInputStream,