添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

The stream that is internally created by the CreateFromDirectory method remains opened and the user can't close it:

This is error message observed when using the below code snippet:

The process cannot access the file 'C:\Users\dyordano\OneDrive - Progress Software Corporation\MyProjects\1640071ZipFileCreateFromDirectory\myzip.zip' because it is being used by another process.

        static void Main(string[] args)
            string archiveFileName = @"..\..\myzip.zip";
            string sourceDirectoryName = @"..\..\Folder";
            File.Delete(archiveFileName);
            Telerik.Windows.Zip.Extensions.ZipFile.CreateFromDirectory(sourceDirectoryName, archiveFileName, Telerik.Windows.Zip.CompressionLevel.Optimal, true);
            using (Stream stream = File.Open(archiveFileName, FileMode.Open))
        }

Workaround:

        static void Main(string[] args)
            string archiveFileName = @"..\..\myzip.zip";
            string sourceDirectoryName = @"..\..\Folder";
            File.Delete(archiveFileName);
          //  Telerik.Windows.Zip.Extensions.ZipFile.CreateFromDirectory(sourceDirectoryName, archiveFileName, Telerik.Windows.Zip.CompressionLevel.Optimal, true);
            CreateFromDirectory(sourceDirectoryName, archiveFileName, Telerik.Windows.Zip.CompressionLevel.Optimal, true);
            using (Stream stream = File.Open(archiveFileName, FileMode.Open))
        private static void CreateFromDirectory(string sourceDirectoryName, string destinationArchiveFileName, Telerik.Windows.Zip.CompressionLevel compressionLevel, bool includeBaseDirectory)
            Encoding entryNameEncoding = null;
            DeflateSettings compressionSettings = new DeflateSettings()
                CompressionLevel = compressionLevel,
                HeaderType = CompressedStreamHeader.None
            char[] directorySeparatorChar = new char[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar };
            sourceDirectoryName = Path.GetFullPath(sourceDirectoryName);
            destinationArchiveFileName = Path.GetFullPath(destinationArchiveFileName);
            FileStream fileStream = File.Open(destinationArchiveFileName, FileMode.CreateNew, FileAccess.Write, FileShare.None); ;
            using (ZipArchive zipArchive = new ZipArchive(fileStream, ZipArchiveMode.Create,false,  entryNameEncoding))
                bool empty = true;
                DirectoryInfo directoryInfo = new DirectoryInfo(sourceDirectoryName);
                string fullName = directoryInfo.FullName;
                if (includeBaseDirectory && directoryInfo.Parent != null)
                    fullName = directoryInfo.Parent.FullName;
                foreach (FileSystemInfo fileSystemInfo in directoryInfo.EnumerateFileSystemInfos("*", SearchOption.AllDirectories))
                    empty = false;
                    int length = fileSystemInfo.FullName.Length - fullName.Length;
                    string entryName = fileSystemInfo.FullName.Substring(fullName.Length, length);
                    entryName = entryName.TrimStart(directorySeparatorChar);
                    DirectoryInfo subfolder = fileSystemInfo as DirectoryInfo;
                    if (subfolder != null)
                        if (IsDirectoryEmpty(subfolder))
                            zipArchive.CreateEntry(string.Concat(entryName, Path.DirectorySeparatorChar));
                        ZipFile.CreateEntryFromFile(zipArchive, fileSystemInfo.FullName, entryName, compressionSettings);
                if (includeBaseDirectory && empty)
                    zipArchive.CreateEntry(string.Concat(directoryInfo.Name, Path.DirectorySeparatorChar));
        private static bool IsDirectoryEmpty(DirectoryInfo directoryInfo)
            bool empty = true;
            using (IEnumerator<FileSystemInfo> enumerator = directoryInfo.EnumerateFileSystemInfos("*", SearchOption.AllDirectories).GetEnumerator())
                if (enumerator.MoveNext())
                    empty = false;
            return empty;
        }

Note: We should ensure that all of the obsolete API that used to use the "leave open" flag don't keep the stream locked.

Hi Joe,

I checked the code snippet from this ticket thread and I can confirm there is an error message when extacting a zip archive that contains an empty folder I logged an item on your behalf in order to investigate this unexpected behavior: ZipLibrary: 7zip reports errors while extracting archive containing empty folders . Please, make sure to subscribe to the task so we can notify you when its status changes.

On the other hand, with the sample project I created the archive could be successfully exported (even with the error message). The output can be seen in the attached " observed.gif "

As for setting the last modified date, you can check the ZipArchive entry`s LastWriteTime property. An example can be found in " Example 4: Set last entry's write time " in the ZipArchive Entry help article.

Regards,
Martin
Progress Telerik

A brand new ThemeBuilder course was just added to the Virtual Classroom. The training course was designed to help you get started with ThemeBuilder for styling Telerik and Kendo UI components for your applications. You can check it out at https://learn.telerik.com
Attached Files:
  • observed.gif
  • The workaround code seems to have an issue: While empty folders do get added to the ZIP file, these do not get extracted when unzipping (neither with 7-ZIP nor with the Windows built-in ZIP extension). I also noted that folders added by this method do not have a "last modified" date in the ZIP file.

    What needs to be done that empty folders added to a ZIP file also get extracted as empty folders?

    Hi,

    I have added a temporary solution for handling the cases when opening an existing zip with the ZipFile.Open method for example:

           static void Main(string[] args)
               string path = @"path-to-file.zip";
               using (ZipArchive zip = OpenAndClose(path, ZipArchiveMode.Read))
                   foreach (var entry in zip.Entries)
                       if (entry.Name == "TemplateSample.docx")
                            entry.ExtractToFile(@"unzipped-file-name.docx", true);
               File.Delete(path);
           public static ZipArchive OpenAndClose(string archiveFileName, ZipArchiveMode mode, Encoding entryNameEncoding=null)
               FileMode fileMode;
               FileAccess fileAccess;
               FileShare fileShare;
               ZipArchive zipArchive;
               switch (mode)
                   case ZipArchiveMode.Read:
                       fileMode = FileMode.Open;
                       fileAccess = FileAccess.Read;
                       fileShare = FileShare.Read;
                       break;
                   case ZipArchiveMode.Create:
                       fileMode = FileMode.CreateNew;
                       fileAccess = FileAccess.Write;
                       fileShare = FileShare.None;
                       break;
                   case ZipArchiveMode.Update:
                       fileMode = FileMode.OpenOrCreate;
                       fileAccess = FileAccess.ReadWrite;
                       fileShare = FileShare.None;
                       break;
                   default:
                       throw new ArgumentOutOfRangeException("mode");
               FileStream fileStream = null;
                   fileStream = File.Open(archiveFileName, fileMode, fileAccess, fileShare);
                   bool leaveOpen = false;
                   // Closing the stream is important because the created archive will remain locked 
                   zipArchive = new ZipArchive(fileStream, mode, leaveOpen, entryNameEncoding);
               catch
                   if (fileStream != null)
                       fileStream.Dispose();
                   throw;
               return zipArchive;
           }

    Regards,
    Dess | Tech Support Engineer, Principal
    Progress Telerik

    Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.