How to tell if a "ZipArchiveEntry" is directory?
Asked Answered
D

3

43

I am handling some 3rd party ZIP files with .Net 4.5.2 System.IO.Compression.ZipArchive class and all works nicely.
However, I need to tell apart file entries from directory entries, preferably without extracting them first.

Is there a way to tell if a ZipArchive entry is a directory without extracting it?

As far as could find out there is no property of ZipArchiveEntry that tells if it is a file or directory.

Derain answered 24/10, 2016 at 16:44 Comment(0)
D
73

Seems like I really do tend to answer my own questions.

Anyway, the answer is straight forward:

If ZipArchiveEntry is a directory it will have its FullName property ending with "/" (e.g. "some_dir/") and its Name property will be empty string ("").

If only someone cared to put that info in the documentation ...

Oh, and there is a catch:
If a directory contains files, there does not have to be a separate ZipArchiveEntry for it.
So, if you are looking for a specific directory you cannot just look for one ZipArchiveEntry with empty Name or with "/" at the end of FullName - you have to parse the whole tree (FullName for each ZipArchiveEntry).

Luckily I had only to check if there is a single common directory for all entries (FullName properties of all ZipArchiveEntry items shoud start with the same string in the form of "folder_name/").

Derain answered 25/10, 2016 at 15:14 Comment(1)
To be safe I always check FullName for both '\' and '/', specially since ZipArchive itself is broken and will save whatever you throw at it without normalizing to using '/' as the standard says.Hatten
Y
6

Old question but I think it has a better solution than the one provided here. ZipArchiveEntry has a property named ExternalAttributes. Looks like this has been available since .Net Framework 4.7.2

According to MS docs "...low order byte is the MS-DOS directory attribute byte...".

Therefore all you need to do is to take the low byte, cast it as FileAttributes and check the attributes if it is a "Directory" or not.

   var lowerByte = (byte)(atributeValue & 0x00FF);
   var attributes = (FileAttributes)lowerByte;

Now just check the attributes to see if it is a directory (folder)

if (attributes.HasFlag(FileAttributes.Directory)) {...}
Yakut answered 21/8, 2022 at 0:42 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Glutamine
T
2

ICSharpZipLib does it like this:

    public bool IsDirectory
    {
        get
        {
            int nameLength = name.Length;
            bool result =
                ((nameLength > 0) &&
                ((name[nameLength - 1] == '/') || (name[nameLength - 1] == '\\'))) ||
                HasDosAttributes(16)
                ;
            return result;
        }
    }

    public bool IsFile
    {
        get
        {
            return !IsDirectory && !HasDosAttributes(8);
        }
    }

one could write these as extension methods for ZipArchiveEntry

Tse answered 25/3, 2020 at 15:47 Comment(1)
Here is the ZipEntry class for ICSharpZipLib on githubPromissory

© 2022 - 2024 — McMap. All rights reserved.