Reputation: 213
According to the Microsoft Docs, the program should throw an IOException
if the destination directory where the zip file is to be extracted already exists. In addition, the "Remarks" section says, "The destination directory cannot already exist." However,
ZipFile.ExtractToDirectory("archive.zip", ".\\output");
works fine (no exceptions) even if output
exists as a directory. Something like
ZipFile.ExtractToDirectory("archive.zip", "\\");
also works without exceptions. So, I'm trying to understand why there are no exceptions when the Microsoft Docs clearly suggest there should be one.
Note: I'm running .NET 5.
Upvotes: 2
Views: 1501
Reputation: 131714
Looks like a documentation error. I opened two GitHub issues for this, one for the source code comments and one for the docs page that's created from them
.NET Core is open source which means we can check the actual source code to see what's going on.
ZipFile.ExtractToDirectory actually calls the ZipFileExtensions.ExtractToDirectory(ZipArchive, String) method:
public static void ExtractToDirectory(string sourceArchiveFileName, string destinationDirectoryName, Encoding? entryNameEncoding, bool overwriteFiles)
{
if (sourceArchiveFileName == null)
throw new ArgumentNullException(nameof(sourceArchiveFileName));
using (ZipArchive archive = Open(sourceArchiveFileName, ZipArchiveMode.Read, entryNameEncoding))
{
archive.ExtractToDirectory(destinationDirectoryName, overwriteFiles);
}
}
In the actual code IOException is not thrown if the target directory exists, even though the doc site says so:
/// <exception cref="IOException">An archive entry?s name is zero-length, contains only whitespace, or contains one or more invalid
/// characters as defined by InvalidPathChars. -or- Extracting an archive entry would have resulted in a destination
/// file that is outside destinationDirectoryName (for example, if the entry name contains parent directory accessors).
/// -or- An archive entry has the same name as an already extracted entry from the same archive.</exception>
public static void ExtractToDirectory(this ZipArchive source, string destinationDirectoryName, bool overwriteFiles)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (destinationDirectoryName == null)
throw new ArgumentNullException(nameof(destinationDirectoryName));
foreach (ZipArchiveEntry entry in source.Entries)
{
entry.ExtractRelativeToDirectory(destinationDirectoryName, overwriteFiles);
}
}
It looks like learn.microsoft.com
is behind the actual source docs.
For completeness, the internal ExtractRelativeToDirectory method explicitly considers an existing destination folder to be a valid case :
internal static void ExtractRelativeToDirectory(this ZipArchiveEntry source, string destinationDirectoryName, bool overwrite)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (destinationDirectoryName == null)
throw new ArgumentNullException(nameof(destinationDirectoryName));
// Note that this will give us a good DirectoryInfo even if destinationDirectoryName exists:
DirectoryInfo di = Directory.CreateDirectory(destinationDirectoryName);
...
Emphasis on :
// Note that this will give us a good DirectoryInfo even if destinationDirectoryName exists
Upvotes: 4