Как извлечь единственный файл из удаленного архивного файла?

Данный

  1. URL архива (например, zip-файл)
  2. Полное имя (включая путь) файла в том архиве

Я ищу путь (предпочтительно в Java) для создания локальной копии того файла, не загружая весь архив сначала.

От моего (ограниченного) понимания это должно быть возможно, хотя я понятия не имею, как сделать это. Я использовал TrueZip, так как это, кажется, поддерживает большое множество типов архивирования, но у меня есть сомнения относительно его способности работать таким способом. У кого-либо есть опыт с такой вещью?

Править: способность также сделать это с tarballs и архивировало tarballs, также важно для меня.

11
задан Oak 4 September 2010 в 11:45
поделиться

3 ответа

Ну, как минимум, вы должны загрузить часть архива, включая сжатые данные файла, который вы хотите извлечь. Это предлагает следующее решение: открыть URLConnection к архиву, получить его входной поток, заключить его в ZipInputStream и несколько раз вызвать getNextEntry () и closeEntry () , чтобы перебрать все записи в файле, пока не дойдете до нужной. Затем вы можете прочитать его данные, используя ZipInputStream.read (...) .

Код Java мог бы выглядеть примерно так:

URL url = new URL("http://example.com/path/to/archive");
ZipInputStream zin = new ZipInputStream(url.getInputStream());
ZipEntry ze = zin.getNextEntry();
while (!ze.getName().equals(pathToFile)) {
    zin.closeEntry(); // not sure whether this is necessary
    ze = zin.getNextEntry();
}
byte[] bytes = new byte[ze.getSize()];
zin.read(bytes);

Это, конечно, не проверено.

10
ответ дан 3 December 2019 в 06:45
поделиться

Я не уверен, есть ли способ вытащить извлекать один файл из ZIP-архива, не скачивая его целиком. Но если вы размещаете ZIP-файл, вы можете создать Java-сервлет, который читает ZIP-файл и возвращает запрошенный файл в ответе:

public class GetFileFromZIPServlet extends HttpServlet{
  @Override
  public void doGet(HttpServletRequest request, HttpServletResponse response)
  throws ServletException, IOException{
    String pathToFile = request.getParameter("pathToFile");

    byte fileBytes[];
    //get the bytes of the file from the ZIP

    //set the appropriate content type, maybe based on the file extension
    response.setContentType("...");

    //write file to the response
    response.getOutputStream().write(fileBytes);
  }
}
0
ответ дан 3 December 2019 в 06:45
поделиться

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

Стандартный Java API поддерживает только чтение ZIP-файлов из локальных файлов и входных потоков. Насколько я знаю, не предусмотрено чтение из удаленных файлов с произвольным доступом.

Поскольку вы используете TrueZip, я рекомендую реализовать de.schlichtherle.io.rof.ReadOnlyFile с помощью Apache HTTP Client и создать de.schlichtherle.util.zip.ZipFile с его помощью.

Это не даст никаких преимуществ для сжатых TAR-архивов, поскольку весь архив сжимается вместе (помимо использования InputStream и его уничтожения после записи).

5
ответ дан 3 December 2019 в 06:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: