2017-11-09 88 views
-3

중첩 된 zip 아카이브에서 파일을 추출하고 메모리에서 처리하려고합니다. 이 질문은 무엇임시 파일을 사용하지 않고 Java로 중첩 된 zip 파일에서 데이터를 읽는 방법?

하지에 대한 :

어떻게 자바로 zip 파일을 읽는
  1. : NO, 질문 등 지퍼 내에서 압축 파일 내에서 zip 파일을 읽는 방법입니다 등등 (중첩 된 zip 파일에서와 같이).

  2. 임시 결과를 디스크에 씁니다. 아니요, 모든 것을 기억하고 있습니다. 결과를 디스크에 일시적으로 기록하는 비효율적 인 방법을 사용하여 많은 답변을 찾았지만 원하는 것은 아닙니다.

예 :

ZipFile를 -> Zipfile1 -> Zipfile2 -> Zipfile3

목표 : 중첩 ZIP 파일들 각각에있는 데이터를 모두 메모리 및 사용을 추출 자바.

ZipFile 대답입니까, 그렇습니까? > Zipfile1

하지만 일단 Zipfile2에 도착하고, 수행 -

ZipFile를 :

ZipInputStream z = new ZipInputStream(zipFile.getInputStream(zipEntry)) ; 
을 아니, 그것은을 위해, 그것은 첫 번째 반복을 위해 작동하지 않습니다

NullPointerException이 발생합니다.

내 코드 :

public class ZipHandler { 

    String findings = new String(); 
    ZipFile zipFile = null; 

    public void init(String fileName) throws AppException{ 

     try { 
     //read file into stream 
     zipFile = new ZipFile(fileName); 
     Enumeration<?> enu = zipFile.entries(); 
     exctractInfoFromZip(enu); 

     zipFile.close(); 
     } catch (FileNotFoundException e) { 
     e.printStackTrace(); 

     } catch (IOException e) { 
      e.printStackTrace(); 
    } 
} 

//The idea was recursively extract entries using ZipFile 
public void exctractInfoFromZip(Enumeration<?> enu) throws IOException, AppException{ 

    try { 
     while (enu.hasMoreElements()) { 
      ZipEntry zipEntry = (ZipEntry) enu.nextElement(); 

      String name = zipEntry.getName(); 
      long size = zipEntry.getSize(); 
      long compressedSize = zipEntry.getCompressedSize(); 

      System.out.printf("name: %-20s | size: %6d | compressed size: %6d\n", 
        name, size, compressedSize); 

      // directory ? 
      if (zipEntry.isDirectory()) { 
       System.out.println("dir found:" + name); 
       findings+=", " + name; 
       continue; 
      } 

      if (name.toUpperCase().endsWith(".ZIP") || name.toUpperCase().endsWith(".GZ")) { 
       String fileType = name.substring(
         name.lastIndexOf(".")+1, name.length()); 

       System.out.println("File type:" + fileType); 
       System.out.println("zipEntry: " + zipEntry); 

       if (fileType.equalsIgnoreCase("ZIP")) { 
//ZipFile here returns a NULL pointer when you try to get the first nested zip 
        ZipInputStream z = new ZipInputStream(zipFile.getInputStream(zipEntry)) ; 
        System.out.println("Opening ZIP as stream: " + name); 

        findings+=", " + name; 

        exctractInfoFromZip(zipInputStreamToEnum(z)); 
       } else if (fileType.equalsIgnoreCase("GZ")) { 
//ZipFile here returns a NULL pointer when you try to get the first nested zip  
        GZIPInputStream z = new GZIPInputStream(zipFile.getInputStream(zipEntry)) ; 
        System.out.println("Opening ZIP as stream: " + name); 

        findings+=", " + name; 

        exctractInfoFromZip(gZipInputStreamToEnum(z)); 
       } else 
        throw new AppException("extension not recognized!"); 
      } else { 
       System.out.println(name); 
       findings+=", " + name; 
      } 
     } 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

    System.out.println("Findings " + findings); 
} 

public Enumeration<?> zipInputStreamToEnum(ZipInputStream zStream) throws IOException{ 

    List<ZipEntry> list = new ArrayList<ZipEntry>();  

    while (zStream.available() != 0) { 
     list.add(zStream.getNextEntry()); 
    } 

    return Collections.enumeration(list); 
} 
+1

_ "(곧 수정 예정)"_ - 부분 질문을 게시하지 마십시오. 게시하기 전에 공식 질문이있을 때까지 기다리십시오. –

+0

주된 문제는 먼저 ZipInputStream에서'getNextEntry()'를 사용하여 올바른 zip 항목을 찾아야한다는 것입니다. – JMax

+0

wronlgy 게시에 대한 죄송합니다. 내가 직장에서 나올 때 게시물을 수정 해 줄거야. 나는 이걸 가지고 정말로 붙어있다. –

답변

1

나는 그것을 시도하지만 당신은 어떤 InputStream that contains a ZIP file as data. Iterate through the entries and when you found the correct entry use the ZipInputStream to create another nested ZipInputStream`을 읽을 수 ZipInputStream를 사용하지 않았습니다.

다음 코드는이를 보여줍니다. 우리가 readme.txt 안에 0.zip이 있고 다시 2.zip에서 압축 된 1.zip으로 압축 된 것을 상상해보십시오. 이제 우리는 readme.txt에서 일부 텍스트를 읽어

try (FileInputStream fin = new FileInputStream("D:/2.zip")) { 
    ZipInputStream firstZip = new ZipInputStream(fin); 
    ZipInputStream zippedZip = new ZipInputStream(findEntry(firstZip, "1.zip")); 
    ZipInputStream zippedZippedZip = new ZipInputStream(findEntry(zippedZip, "0.zip")); 

    ZipInputStream zippedZippedZippedReadme = findEntry(zippedZippedZip, "readme.txt"); 
    InputStreamReader reader = new InputStreamReader(zippedZippedZippedReadme); 
    char[] cbuf = new char[1024]; 
    reader.read(cbuf); 
    System.out.println(new String(cbuf)); 
    ..... 

public static ZipInputStream findEntry(ZipInputStream in, String name) throws IOException { 
    ZipEntry entry = null; 
    while ((entry = in.getNextEntry()) != null) { 
     if (entry.getName().equals(name)) { 
      return in; 
     } 
    } 
    return null; 
} 

참고 코드가 정말 못생긴 아무것도 닫히지 않습니다 않으며 오류를 확인한다. 어떻게 작동하는지 보여주는 최소화 된 버전 일뿐입니다.

이론적으로 다른 ZipInputStreams에 몇 개의 ZipInputStream을 연결할 수 있는지 제한이 없습니다. 데이터는 임시 파일에 기록되지 않습니다. 암호 해독은 각 InputStream을 읽을 때만 수행됩니다.

+0

Jmax가 귀하의 게시물에 감사드립니다. 이 파일을 확인하십시오 –

+0

Jmax, 원본 input.zip 파일 내의 파일 이름을 모르겠습니다. 중첩 된 zip이있는 입력 zip 파일에는 파일, 디렉토리 구조 및 zip 파일이 들어 있습니다. 예. 루트 폴더 input.zip --file.txt --inputNested.zip --nested 폴더 ---- file2.wht ----inputNested2.zip 등 등 –

+0

그런 다음 엔트리를 열거하고 항목 이름/파일 이름을 확인하고 원하는대로 수행하십시오. – JMax

0

이 내가 메모리에 파일을 압축 해제 할 수있는 방법입니다

코드는 AT ALL 깨끗하지 않습니다,하지만 나는 규칙이 뭔가 작업을 게시 할 수 있습니다 이해, 그래서 나는이 희망 그래서

도와 줘야

내가하는 일은 재귀 적 방법을 사용하여 복잡한 ZIP 파일을 탐색하고 폴더 다른 내부 지퍼 파일을 추출하고 결과를 메모리에 저장하여 나중에 사용할 수 있습니다.

홈페이지 일들이 내가 당신과 함께 공유하려는 발견 : 당신은 zip 파일을 중첩 한 경우

1 ZipFile를 쓸모 이 내가 단지 압축 해제 재귀 프로그래밍을 사용하는 기본 우편의 InputStream 및 OutputStream에 3을 사용해야합니다 중첩 된 우편 번호

package course.hernan; 

import java.io.BufferedInputStream; 

import java.io.BufferedOutputStream; 
import java.io.ByteArrayInputStream; 
import java.io.ByteArrayOutputStream; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.util.ArrayDeque; 
import java.util.Deque; 
import java.util.LinkedHashMap; 
import java.util.List; 
import java.util.Map; 
import java.util.zip.ZipEntry; 
import java.util.zip.ZipInputStream; 
import java.util.zip.ZipOutputStream; 

import org.apache.commons.io.IOUtils; 

public class FileReader { 

private static final int BUFFER_SIZE = 2048; 

    public static void main(String[] args) { 
     try { 
      File f = new File("DIR/inputs.zip"); 
      FileInputStream fis = new FileInputStream(f); 
      BufferedInputStream bis = new BufferedInputStream(fis); 
      ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
      BufferedOutputStream bos = new BufferedOutputStream(baos); 
      byte[] buffer = new byte[BUFFER_SIZE]; 
      while (bis.read(buffer, 0, BUFFER_SIZE) != -1) { 
       bos.write(buffer); 
      } 

      bos.flush(); 
      bos.close(); 
      bis.close(); 

      //This STACK has the output byte array information 
      Deque<Map<Integer, Object[]>> outputDataStack = ZipHandler1.unzip(baos); 


     } catch (FileNotFoundException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 
}  
package course.hernan; 

import java.io.BufferedInputStream; 
import java.io.BufferedOutputStream; 
import java.io.ByteArrayInputStream; 
import java.io.ByteArrayOutputStream; 
import java.util.ArrayDeque; 
import java.util.ArrayList; 
import java.util.Deque; 
import java.util.HashMap; 
import java.util.LinkedHashMap; 
import java.util.List; 
import java.util.Map; 
import java.util.SortedMap; 
import java.util.zip.ZipEntry; 
import java.util.zip.ZipInputStream; 

import org.apache.commons.lang3.StringUtils; 

public class ZipHandler1 { 

    private static final int BUFFER_SIZE = 2048; 

    private static final String ZIP_EXTENSION = ".zip"; 
    public static final Integer FOLDER = 1; 
    public static final Integer ZIP = 2; 
    public static final Integer FILE = 3; 


    public static Deque<Map<Integer, Object[]>> unzip(ByteArrayOutputStream zippedOutputFile) { 

    try { 

     ZipInputStream inputStream = new ZipInputStream(
      new BufferedInputStream(new ByteArrayInputStream(
       zippedOutputFile.toByteArray()))); 

     ZipEntry entry; 

     Deque<Map<Integer, Object[]>> result = new ArrayDeque<Map<Integer, Object[]>>(); 

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

     LinkedHashMap<Integer, Object[]> map = new LinkedHashMap<Integer, Object[]>(); 
     ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 
     System.out.println("\tExtracting entry: " + entry); 
     int count; 
     byte[] data = new byte[BUFFER_SIZE]; 

     if (!entry.isDirectory()) { 
      BufferedOutputStream out = new BufferedOutputStream(
       outputStream, BUFFER_SIZE); 

      while ((count = inputStream.read(data, 0, BUFFER_SIZE)) != -1) { 
      out.write(data, 0, count); 
      } 

      out.flush(); 
      out.close(); 

      // recursively unzip files 
      if (entry.getName().toUpperCase().endsWith(ZIP_EXTENSION.toUpperCase())) { 
      map.put(ZIP, new Object[] {entry.getName(), unzip(outputStream)}); 
      result.add(map); 
      //result.addAll(); 
      } else { 
      map.put(FILE, new Object[] {entry.getName(), outputStream}); 
      result.add(map); 
      } 
     } else { 
      map.put(FOLDER, new Object[] {entry.getName(), unzip(outputStream)}); 
      result.add(map); 
     } 
     } 

     inputStream.close(); 

     return result; 

    } catch (Exception e) { 
     throw new RuntimeException(e); 
    } 
    }