Как получить байты из внутреннего файла в zip-файле и создать новый файл-объект [duplicate]

С января 2013 года GitHub включил кнопку «Отключить» рядом с каждой веткой на странице «Ветки».

Соответствующая запись в блоге: Создание и удаление ветвей

42
задан S Jagdeesh 27 March 2013 в 20:54
поделиться

5 ответов

Если вам интересно, как получить содержимое файла с каждого ZipEntry, на самом деле это довольно просто. Вот пример кода:

public static void main(String[] args) throws IOException {
    ZipFile zipFile = new ZipFile("C:/test.zip");

    Enumeration<? extends ZipEntry> entries = zipFile.entries();

    while(entries.hasMoreElements()){
        ZipEntry entry = entries.nextElement();
        InputStream stream = zipFile.getInputStream(entry);
    }
}

Как только у вас есть InputStream, вы можете прочитать его, как хотите.

115
ответ дан Rodrigo Sasaki 26 August 2018 в 01:49
поделиться

Пример кода, который вы можете использовать, чтобы Tika позаботилась о файлах контейнера для вас. http://wiki.apache.org/tika/RecursiveMetadata

Создайте то, что я могу сказать, принятое решение не будет работать для случаев, когда есть вложенные zip-файлы. Тика, однако, позаботится и о таких ситуациях.

3
ответ дан Harinder 26 August 2018 в 01:49
поделиться

Начиная с Java 7, NIO Api обеспечивает лучший и более общий способ доступа к содержимому файлов Zip или Jar. Фактически, теперь это унифицированный API, который позволяет обрабатывать Zip-файлы в точности как обычные файлы.

Чтобы извлечь все файлы, содержащиеся внутри zip-файла в этом API, вы должны сделать это:

В Java 8:

private void extractAll(URI fromZip, Path toDirectory) throws IOException{
    FileSystems.newFileSystem(fromZip, Collections.emptyMap())
            .getRootDirectories()
            .forEach(root -> {
                // in a full implementation, you'd have to
                // handle directories 
                Files.walk(root).forEach(path -> Files.copy(path, toDirectory));
            });
}

В java 7:

private void extractAll(URI fromZip, Path toDirectory) throws IOException{
    FileSystem zipFs = FileSystems.newFileSystem(fromZip, Collections.emptyMap());

    for(Path root : zipFs.getRootDirectories()) {
        Files.walkFileTree(root, new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) 
                    throws IOException {
                // You can do anything you want with the path here
                Files.copy(file, toDirectory);
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) 
                    throws IOException {
                // In a full implementation, you'd need to create each 
                // sub-directory of the destination directory before 
                // copying files into it
                return super.preVisitDirectory(dir, attrs);
            }
        });
    }
}
27
ответ дан LordOfThePigs 26 August 2018 в 01:49
поделиться

Из-за условия в while цикл может никогда не прерываться:

while (entry != null) {
  // If entry never becomes null here, loop will never break.
}

Вместо проверки null вы можете попробовать следующее:

ZipEntry entry = null;
while ((entry = zip.getNextEntry()) != null) {
  // Rest of your code
}
10
ответ дан Nishant Shreshth 26 August 2018 в 01:49
поделиться

Мой способ достичь этого - создать класс обертки ZipInputStream, который будет обрабатывать, который будет обеспечивать только поток текущей записи:

Класс оболочки:

public class ZippedFileInputStream extends InputStream {

    private ZipInputStream is;

    public ZippedFileInputStream(ZipInputStream is){
        this.is = is;
    }

    @Override
    public int read() throws IOException {
        return is.read();
    }

    @Override
    public void close() throws IOException {
        is.closeEntry();
    }

}

Использование этого:

    ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream("SomeFile.zip"));

    while((entry = zipInputStream.getNextEntry())!= null) {

     ZippedFileInputStream archivedFileInputStream = new ZippedFileInputStream(zipInputStream);

     //... perform whatever logic you want here with ZippedFileInputStream 

     // note that this will only close the current entry stream and not the ZipInputStream
     archivedFileInputStream.close();

    }
    zipInputStream.close();

Одно из преимуществ такого подхода: InputStreams передаются в качестве аргументов методам, которые обрабатывают их, и эти методы имеют тенденцию немедленно закрывать входной поток после того, как они будут выполнены с ним.

2
ответ дан Vilius 26 August 2018 в 01:49
поделиться
Другие вопросы по тегам:

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