In my current project I needed to get a list of files that were in a zip file. In the past when I needed to do this I would have used J# and just added a reference. Since J# is not included I wanted to see if there was a different way to achieve this.
Microsoft has since added a System.IO.Packaging namespace that includes the ZipPackage class. I added a reference to WindowsBase.dll because that is where the ZipPackage class is.
As I researched about using the class I found that it does not provide a public method to get a list of the files. As I looked at the data I noticed a field named _zipArchive of the type MS.Internal.IO.Zip.ZipArchive. I looked further in the field and noticed a property named ZipFileInfoDictionary which is a System.Collections.Hashtable.
By using reflection I was able to access the _zipArchive and the ZipFileInfoDictionary to retrieve the file list.
I have created the following extension method called GetFileList to return the list of files in the zip file.
public static List<string> GetFileList(this ZipPackage zp) { List<string> list = null; try { var zipArchiveProperty = zp.GetType().GetField("_zipArchive", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Instance); var zipArchive = zipArchiveProperty.GetValue(zp); var zipFileInfoDictionaryProperty = zipArchive.GetType().GetProperty("ZipFileInfoDictionary", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Instance); var zipFileInfoDictionary = zipFileInfoDictionaryProperty.GetValue(zipArchive, null) as Hashtable; var query = from System.Collections.DictionaryEntry de in zipFileInfoDictionary select de.Key.ToString(); list = query.ToList(); } catch (NotSupportedException nse) { throw; } return list; } |
To call the method I used the following:
private List<string> GetFileListFromZipFile(FileInfo zipFileName) { List<string> list = null; try { var zp = ZipPackage.Open(zipFileName.FullName, FileMode.Open, FileAccess.Read, FileShare.Read) as ZipPackage; list = zp.GetFileList(); } catch (NotSupportedException nse) { throw; } return list; } |
I ended up having to use the FileShare.Read because I was getting a file in use exception.