ZIP 아카이브를 플랫하게 만들기

zip 아카이브 안에 다른 zip 아카이브가 있을 수 있습니다. 플랫 구조를 얻기 위해 중첩된 zip 아카이브의 콘텐츠를 상위 아카이브로 추출할 수 있습니다.

현재 아카이브 구조
outer.zip
 ├first.txt
 ├inner.zip
 │ ├game.exe
 │ └subitem.bin
 └picture.gif
원하는 아카이브 구조
flatten.zip
 ├first.txt
 ├picture.gif
 ├game.exe
 └subitem.bin

Aspose.Zip에 익숙하지 않다면 먼저 zip 아카이브 추출 방법을 읽어보세요.

전체적인 설명

먼저 아카이브의 모든 항목을 나열해야 합니다. 일반 항목은 그대로 유지되어야 하며 압축을 풀어서도 안 됩니다. 아카이브 자체인 항목은 메모리로 추출되어 외부 아카이브에서 제거되어야 합니다. 해당 콘텐츠는 기본 아카이브에 포함되어야 합니다.

아카이브 항목 감지

어떤 항목이 아카이브 자체인지 결정해 보겠습니다. 항목 이름을 확장하면 이를 알 수 있습니다. 나중에 해당 항목을 기본 아카이브에서 제거하므로 해당 항목을 목록에 보관하십시오.

1if (entry.Name.EndsWith(".zip", StringComparison.InvariantCultureIgnoreCase)) {
2    entriesToDelete.Add(entry);
3    ...
4}

항목의 내용을 메모리로 추출하는 중

Aspose.Zip을 사용하면 파일뿐만 아니라 쓰기 가능한 모든 스트림으로 zip 항목의 내용을 추출할 수 있습니다. 따라서 중첩된 아카이브를 메모리 스트림으로 추출할 수 있습니다.

참고: 가상 메모리는 추출된 모든 콘텐츠를 저장할 만큼 충분히 커야 합니다.

1MemoryStream innerCompressed = new MemoryStream();
2entry.Open().CopyTo(innerCompressed); 

이후 innerCompressed 스트림에는 내부 아카이브 자체가 포함됩니다. 아카이브 생성자를 사용하면 제공된 스트림의 압축을 풀 수 있습니다. 따라서 우리는 그것을 추출할 수도 있습니다:

1Archive inner = new Archive(innerCompressed);

항목 제외

특정 방법을 사용하여 zip 아카이브에서 항목을 제거할 수 있습니다.

1foreach (ArchiveEntry e in entriesToDelete) { outer.DeleteEntry(e); }

모두 모아보세요

완전한 알고리즘은 다음과 같습니다.

 1    using (Archive outer = new Archive("outer.zip"))
 2    {
 3        List<ArchiveEntry> entriesToDelete = new List<ArchiveEntry>();
 4        List<string> namesToInsert = new List<string>();
 5        List<MemoryStream> contentToInsert = new List<MemoryStream>();
 6
 7        foreach (ArchiveEntry entry in outer.Entries)
 8        {
 9            if (entry.Name.EndsWith(".zip", StringComparison.InvariantCultureIgnoreCase)) // Find an entry which is an archive itself
10            {
11                entriesToDelete.Add(entry); // Keep reference to the entry in order to remove it from the archive later
12                MemoryStream innerCompressed = new MemoryStream();
13                entry.Open().CopyTo(innerCompressed); //This extracts the entry to a memory stream
14
15                using (Archive inner = new Archive(innerCompressed)) // We know that content of the entry is an zip archive so we may extract
16                {
17                    foreach (ArchiveEntry ie in inner.Entries) // Loop over entries of inner archive
18                    {
19                        namesToInsert.Add(ie.Name); // Keep the name of inner entry.
20                        MemoryStream content = new MemoryStream();
21                        ie.Open().CopyTo(content);
22                        contentToInsert.Add(content); // Keep the content of inner entry.
23                    }
24                }
25            }
26        }
27
28        foreach (ArchiveEntry e in entriesToDelete) 
29            outer.DeleteEntry(e); // Delete all the entries which are archives itself
30
31        for (int i = 0; i < namesToInsert.Count; i++)    
32            outer.CreateEntry(namesToInsert[i], contentToInsert[i]); // Adds entries which were entries of inner archives
33        
34        outer.Save("flatten.zip");
35    }

Subscribe to Aspose Product Updates

Get monthly newsletters & offers directly delivered to your mailbox.