繁体   English   中英

GZIPInputStream:从解压缩的文件中读取前n个字节

[英]GZIPInputStream: Read first n bytes from decompressed file

我有成千上万个通过HTTP访问的GZIP文件。 每个文件的大小上限为几百MB。 我需要从这些压缩文件中的文件读取前几千字节(标头)。

这是我目前的方法:

URL url = new URL("http://example.com/file123.gz");
DataInputStream ds = new DataInputStream(new GZIPInputStream(url.openStream()));
byte[] header = new byte[5760];
ds.readFully(header);

我需要做的是从此GZIP文件中的文件中下载前5760个字节,但是我不希望Java下载整个文件(通常多于几个MB)。

我的问题是-Java是先下载整个GZIP文件然后解压缩,还是只下载必要的数据量来填充byte[5760]缓冲区? 如何找到从HTTP服务器实际下载了多少数据?

Java是先下载整个GZIP文件然后解压缩,还是下载所需数量的数据以填充byte [5760]缓冲区?

它更接近后者。 Java不会先读取整个文件。 相反, url.openStream()给您一个“套接字流”,该套接字直接从套接字读取数据。

内核端套接字数据结构中可能缓冲了一些数据, GZIPInputStream可能缓冲了一些数据。 但这绝对是一个有限的数目。 因此,服务器可能会发送比应用程序实际消耗更多的数据,但不太可能发送整个(兆字节大小)的文件。

如何找到从HTTP服务器实际下载了多少数据?

这很难衡量,甚至很难定义。 根据上下文,您似乎对服务器发送的数量确实很感兴趣。 唯一实际的测量方法是在服务器端,甚至很难。 (如果您真的不需要找出这个,我建议您不要麻烦尝试...)

您无法指定实际将下载多少数据。

满足您的请求的Web服务器将打开请求的文件,并通过tcp连接发送全部内容(以http响应标头开头)。

这意味着整个文件将被发送给您,除了在正确的时间关闭基础连接之外,您将无法执行任何操作,但这将不容易实现,尤其是无法可靠地工作。 这意味着:您从inputstream中读取了5760字节(此时,它已经包含了超过5760字节!),然后关闭流和连接-但这并不意味着在此期间接收到更多数据

要弄清您实际收到了多少,您必须完全阅读输入流并检查其长度。

如果Web服务器支持字节范围请求,则您可以告诉它仅下载第一个(例如)10kB压缩数据(以确保在解压缩时至少获得5760字节)。

URL url = new URL("http://example.com/file123.gz");
URLConnection connection = url.openConnection();
connection.setRequestProperty("Range", "bytes=0-9999");
DataInputStream ds = new DataInputStream(
                         new GZIPInputStream(connection.getInputStream()));
byte[] header = new byte[5760];
ds.readFully(header);

您可能需要捕获在此过程中引发的任何异常,然后在没有范围标头的情况下重试(尽管不了解它的服务器应该无论如何都要发送整个文件)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM