GZIPInputStream: чтение первых n байтов из распакованного файла

1

У меня есть набор из тысяч файлов GZIP, к которым я обращаюсь через HTTP. Размер каждого файла может составлять до нескольких сотен МБ. Мне нужно прочитать первые несколько килобайт (заголовок) из файла внутри этих сжатых файлов.

Это мой нынешний подход:

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);

Что мне нужно сделать, так это загрузить первые 5760 байт из файла внутри этого файла GZIP, но я не хочу, чтобы Java загружала весь файл (который обычно превышает несколько МБ).

Мой вопрос: действительно ли Java сначала загружает весь файл GZIP, а затем распаковывает его или загружает только необходимое количество данных для заполнения буфера byte[5760]? Как узнать, сколько данных было фактически загружено с HTTP-сервера?

  • 0
    Существует заголовок HTTP для ограниченной загрузки: что-то вроде Range: bytes=0..6000 должно Range: bytes=0..6000 серверу не отправлять весь файл. Я не знаю, являются ли значения диапазона до или после сжатия, и AFAIK нет никакой гарантии, что сервер выполнит это.
Теги:
optimization
gzip
inputstream

3 ответа

2
Лучший ответ

Сначала Java загружает весь файл GZIP, а затем распаковывает его или загружает только необходимое количество данных для заполнения буфера [5760]?

Это ближе к последнему. Сначала Java не читает весь файл. Вместо этого url.openStream() предоставляет вам "поток сокетов", который считывает данные непосредственно из сокета.

Вероятно, будут некоторые данные, буферизированные в структурах данных сокета на стороне ядра, и, возможно, больше в GZIPInputStream. Но это определенно ограниченная сумма. Поэтому вполне вероятно, что сервер отправит больше данных, чем ваше приложение фактически потребляет, но маловероятно, что он отправит целые (мегабайтные) файлы.

Как узнать, сколько данных было фактически загружено с HTTP-сервера?

Его трудно измерить и даже трудно определить. Основываясь на контексте, кажется, что вы действительно заинтересованы в том, сколько сервер отправляет. Единственный практический способ измерить это на стороне сервера, и даже это сложно. (Если вам действительно не нужно это выяснять, я рекомендую вам не пытаться...)

0

Если веб-сервер поддерживает запросы байтового диапазона, вы можете сказать ему, чтобы он загружал только первые (скажем) 10 Кбайт сжатых данных (чтобы обеспечить получение по меньшей мере 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);

Возможно, вам придется поймать любые исключения, вызванные этим процессом, и повторить попытку без заголовка диапазона (хотя сервер, который не понимает его, должен просто отправить весь файл в любом случае).

0

Вы не можете указать, сколько данных действительно будет загружено.

Веб-сервер, который обслуживает ваш запрос, откроет запрошенный файл и отправит весь контент (которому предшествуют заголовки ответов HTTP) через tcp-соединение.

Это означает, что весь файл будет отправлен вам, и вы ничего не можете с этим поделать, кроме как закрыть базовое соединение в нужное время, но это будет нелегко сделать и особенно не работать надежно. Это означает: вы читаете 5760 байт из входного потока (который на данный момент уже содержит больше 5760 байт!), А затем закрывает поток и соединение - но это не означает, что за это время было получено намного больше данных.

Чтобы узнать, сколько вы получили, вы должны полностью прочитать свой входной поток и проверить его длину.

  • 0
    Чтобы выяснить, сколько на самом деле нужно получить, вы можете посмотреть на длину контента.
  • 0
    Да, но это спецификация сервера о том, как долго контент. Это не то же самое значение, что и длина данных в вашем входном потоке, если вы полностью не получили данные.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню