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

Java GZIPInputStream:从解压缩文件中读取前n个字节,java,optimization,gzip,inputstream,Java,Optimization,Gzip,Inputstream,我有一组数以千计的GZIP文件,我正在通过HTTP访问这些文件。每个文件的大小可能高达数百MB。我需要从这些压缩文件中的文件中读取前几个千字节(头) 这是我目前的做法: URL url = new URL("http://example.com/file123.gz"); DataInputStream ds = new DataInputStream(new GZIPInputStream(url.openStream())); byte[] header = new byte[5760];

我有一组数以千计的GZIP文件,我正在通过HTTP访问这些文件。每个文件的大小可能高达数百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文件,然后解压缩,还是只下载必要的数据量来填充
字节[5760]
缓冲区?如何查找从HTTP服务器实际下载的数据量?

您无法指定实际下载的数据量

为您的请求提供服务的Web服务器将打开请求的文件,并通过tcp连接发送整个内容(前面是http响应头)

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

要了解您实际收到了多少,您必须完整地读取输入流并检查其长度

Java是先下载整个GZIP文件然后解压,还是只下载必要的数据量来填充字节[5760]缓冲区

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

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

如何找到从HTTP服务器实际下载的数据量


这很难衡量,甚至很难界定。根据上下文,您似乎真的对服务器发送的量感兴趣。唯一实用的测量方法是在服务器端,即使这样也很困难。(如果您真的不需要了解这一点,我建议您不要费心尝试…

如果web服务器支持字节范围请求,那么您可以告诉它只下载第一个(比如)10kB的压缩数据(以确保解压缩时至少获得5760字节)


您可能需要捕获在此过程中引发的任何异常,并在不使用范围标头的情况下重试(尽管不理解它的服务器应该只发送整个文件)。

要确定实际接收的文件量,可以查看内容长度。是,但这是服务器对内容长度的规定。除非您完全接收到数据,否则它的值与inputstream中数据的长度不同。有一个HTTP头用于有限下载:类似于
Range:bytes=0..6000的内容应该告诉服务器不要发送整个文件。我不知道范围值是在压缩之前还是压缩之后,而且恐怕也不能保证服务器会遵守它。
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);