SharpZipLib icon indicating copy to clipboard operation
SharpZipLib copied to clipboard

Add folder, unable to decompress

Open Luohui109 opened this issue 1 year ago • 0 comments

Describe the bug

Version SharpZipLib. 1.3.3 I'm not sure that version 4 has this issue “Stored, but compressed != uncompressed”

Reproduction Code

No response

Steps to reproduce

Step 1: namespace SoluM.Utils.Zip { using ICSharpCode.SharpZipLib.Zip; using System.Collections; using System.IO; using System.Threading;

/// <summary>
/// ICSharpCode.SharpZipLib.Zip
/// </summary>
public class ZipHelper
{
    private const int BufferSize = 1024;

    public const int CompressionLevelMin = 0;

    public const int CompressionLevelMax = 9;
	
	internal static int CheckCompressionLevel(int compressionlevel)
    {
        return compressionlevel < CompressionLevelMin ? CompressionLevelMin : compressionlevel > CompressionLevelMax ? CompressionLevelMax : compressionlevel;
    }
	
	public class FileEntry
	{
		/// <summary>
		/// 
		/// </summary>
		public string Name { get; set; }
		/// <summary>
		/// 
		/// </summary>
		public string FullName { get; set; }
		/// <summary>
		/// 
		/// </summary>
		public string ZipEntryName { get; set; }
		/// <summary>
		/// 
		/// </summary>
		public bool IsDirectory { get; set; }
		/// <summary>
		/// 
		/// </summary>
		public string Extension { get; set; }
		/// <summary>
		/// 
		/// </summary>
		public long Length { get; set; }
		/// <summary>
		/// 
		/// </summary>
		public bool ReadOnly { get; set; }
		/// <summary>
		/// 
		/// </summary>
		public FileAttributes Attributes { get; set; }
		/// <summary>
		/// 
		/// </summary>
		public DateTime CreationTime { get; set; }
		/// <summary>
		/// 
		/// </summary>
		public DateTime LastAccessTime { get; set; }
		/// <summary>
		/// 
		/// </summary>
		public DateTime LastWriteTime { get; set; }
	}

public static bool IsDiskOnly(string path) { bool result = false;

        if (!string.IsNullOrWhiteSpace(path) && (File.Exists(path) || Directory.Exists(path)))
        {
            DirectoryInfo directoryInfo = new DirectoryInfo(path);

            result = directoryInfo.Root.FullName == directoryInfo.FullName;
        }

        return result;
    }

    public static bool HasDescendants(string path)
    {
        bool result = false;

        if (!string.IsNullOrWhiteSpace(path) && (File.Exists(path) || Directory.Exists(path)))
        {
            if (File.Exists(path))
            {
                result = true;
            }
            else if (Directory.Exists(path))
            {
                result = Directory.GetFiles(path, "*.*", SearchOption.AllDirectories).Length > 0;
            }
        }

        return result;
    }
	public static List<FileEntry> GetFileEntry(string path, bool includedemptydir = true)
	{
		List<FileEntry> fileEntryList = new List<FileEntry>();

		FileEntry fileEntry;
		FileInfo fileInfo;
		DirectoryInfo directoryInfo;

		//
		if (!string.IsNullOrWhiteSpace(path))
		{
			//
			if (path.EndsWith(@"\"))
			{
				path = path.Remove(path.LastIndexOf(@"\"));
			}

			if (File.Exists(path))
			{
				fileInfo = new FileInfo(path);
				fileEntry = new FileEntry();
				fileEntry.Name = fileInfo.Name;
				fileEntry.FullName = fileInfo.FullName;
				fileEntry.ZipEntryName = fileInfo.Name;
				fileEntry.IsDirectory = false;
				fileEntry.Extension = fileInfo.Extension;
				fileEntry.Length = fileInfo.Length;
				fileEntry.ReadOnly = fileInfo.IsReadOnly;
				fileEntry.Attributes = fileInfo.Attributes;
				fileEntry.CreationTime = fileInfo.CreationTime;
				fileEntry.LastAccessTime = fileInfo.LastAccessTime;
				fileEntry.LastWriteTime = fileInfo.LastWriteTime;
				fileEntryList.Add(fileEntry);
			}
			else if (Directory.Exists(path))
			{
				if (!IsDiskOnly(path))
				{
					if (includedemptydir || HasDescendants(path))
					{
						string parentPath = Path.GetDirectoryName(path) + @"\";

						if (parentPath.EndsWith(@":\\"))
						{
							parentPath = parentPath.Replace(@"\\", @"\");
						}

						//先将顶级文件夹压入
						directoryInfo = new DirectoryInfo(path);
						fileEntry = new FileEntry();
						fileEntry.Name = directoryInfo.Name;
						fileEntry.FullName = directoryInfo.FullName;
						fileEntry.ZipEntryName = directoryInfo.FullName.Replace(parentPath, "");
						fileEntry.IsDirectory = true;
						fileEntry.Extension = "";
						fileEntry.Length = 0;
						fileEntry.ReadOnly = default;
						fileEntry.Attributes = directoryInfo.Attributes;
						fileEntry.CreationTime = directoryInfo.CreationTime;
						fileEntry.LastAccessTime = directoryInfo.LastAccessTime;
						fileEntry.LastWriteTime = directoryInfo.LastWriteTime;
						fileEntryList.Add(fileEntry);

						//
						string[] directories = Directory.GetDirectories(path, "*.*", SearchOption.AllDirectories);
						foreach (string dir in directories)
						{
							if (includedemptydir || HasDescendants(dir))
							{
								directoryInfo = new DirectoryInfo(dir);
								fileEntry = new FileEntry();
								fileEntry.Name = directoryInfo.Name;
								fileEntry.FullName = directoryInfo.FullName;
								fileEntry.ZipEntryName = directoryInfo.FullName.Replace(parentPath, "");
								fileEntry.IsDirectory = true;
								fileEntry.Extension = "";
								fileEntry.Length = 0;
								fileEntry.ReadOnly = default;
								fileEntry.Attributes = directoryInfo.Attributes;
								fileEntry.CreationTime = directoryInfo.CreationTime;
								fileEntry.LastAccessTime = directoryInfo.LastAccessTime;
								fileEntry.LastWriteTime = directoryInfo.LastWriteTime;
								fileEntryList.Add(fileEntry);
							}
						}
						//
						string[] files = Directory.GetFiles(path, "*.*", SearchOption.AllDirectories);
						foreach (string file in files)
						{
							fileInfo = new FileInfo(file);
							fileEntry = new FileEntry();
							fileEntry.Name = fileInfo.Name;
							fileEntry.FullName = fileInfo.FullName;
							fileEntry.ZipEntryName = fileInfo.FullName.Replace(parentPath, "");
							fileEntry.IsDirectory = false;
							fileEntry.Extension = fileInfo.Extension;
							fileEntry.Length = fileInfo.Length;
							fileEntry.ReadOnly = fileInfo.IsReadOnly;
							fileEntry.Attributes = fileInfo.Attributes;
							fileEntry.CreationTime = fileInfo.CreationTime;
							fileEntry.LastAccessTime = fileInfo.LastAccessTime;
							fileEntry.LastWriteTime = fileInfo.LastWriteTime;
							fileEntryList.Add(fileEntry);
						}
					}
				}
			}
		}

		return fileEntryList;
	}
	public static List<FileEntry> GetFileEntry(IEnumerable<string> pathlist, bool includedemptydir = true)
	{
		List<FileEntry> fileEntryList = new List<FileEntry>();

		foreach (string path in pathlist)
		{
			fileEntryList.AddRange(GetFileEntry(path));
		}

		return fileEntryList;
	}

	public static string Compress(IEnumerable<string> sourcepathlist, string zipfilepath = null, string comment = null, string password = null, int compressionlevel = 6)
	{
		string result = null;

		try
		{
			//
			if (sourcepathlist == null || !(sourcepathlist.Count() > 0))
			{
				throw new Exception("待添加到压缩包的全路径文件或文件夹列表不能为空、NULL或空白字符!");
			}
			//
			foreach (string sourcepath in sourcepathlist)
			{
				if (string.IsNullOrWhiteSpace(sourcepath))
				{
					throw new Exception("待添加到压缩包的全路径文件或文件夹列表中的元素不能为空、NULL或空白字符!");
				}

				if (!(File.Exists(sourcepath) || Directory.Exists(sourcepath)))
				{
					throw new Exception($"待添加到压缩包的全路径文件或文件夹列表中元素[{sourcepath}]在存储设备上不存在!");
				}
			}

			//获取文件、文件夹列表
			List<FileEntry> fileEntryList = GetFileEntry(sourcepathlist);

			//检测目标文件夹是否存在,如果不存在则建立
			string zipFileDirectory = Path.GetDirectoryName(zipfilepath);
			if (!Directory.Exists(zipFileDirectory))
			{
				Directory.CreateDirectory(zipFileDirectory);
			}

			//创建压缩文件,若存在则覆盖
			using (FileStream zipStream = File.Create(zipfilepath))
			{
				using (ZipOutputStream zipOutputStream = new ZipOutputStream(zipStream))
				{
					zipOutputStream.Password = password;//设置密码
					zipOutputStream.SetComment(comment);//添加注释
					zipOutputStream.SetLevel(CheckCompressionLevel(compressionlevel));//设置压缩等级

					foreach (FileEntry fileEntry in fileEntryList)//从List取文件添加到压缩文件
					{
						if (fileEntry.IsDirectory)
						{
							ZipEntry zipEntry = new ZipEntry(fileEntry.ZipEntryName + @"/");
							zipOutputStream.PutNextEntry(zipEntry);
						}
						else
						{
							using (FileStream fileStream = File.OpenRead(fileEntry.FullName))
							{
								ZipEntry zipEntry = new ZipEntry(fileEntry.ZipEntryName);
								zipEntry.DateTime = fileEntry.LastWriteTime;
								zipEntry.Size = fileEntry.Length;
								zipOutputStream.PutNextEntry(zipEntry);

								byte[] buffer = new byte[BufferSize];
								int read = 0;
								while ((read = fileStream.Read(buffer, 0, BufferSize)) > 0)
								{
									zipOutputStream.Write(buffer, 0, read);
								}
							}
						}
					}

					//
					zipOutputStream.Flush();
				}
			}

			//
			result = zipfilepath;
		}
		catch (System.Exception ex)
		{
			if (File.Exists(zipfilepath))
			{
				File.Delete(zipfilepath);
			}
			throw new Exception("压缩失败!", ex);
		}

		return result;
	}

	public static string Decomparess(string zipfilepath, string destinationdirectory = null, string password = null)
	{
		string result = null;

		//
		if (string.IsNullOrWhiteSpace(zipfilepath))
		{
			throw new Exception("待解压缩文件[{zipfilepath}]不能为空、NULL或空白字符!");
		}
		//
		if (!File.Exists(zipfilepath))
		{
			throw new FileNotFoundException($"待解压缩文件[{zipfilepath}]在存储设备上不存在!");
		}

                  //
                  FileInfo fileInfo = new FileInfo(zipfilepath);
	     string directory = fileInfo.DirectoryName + @"\";
	     string filename = fileInfo.Name.Substring(0, fileInfo.Name.Length - fileInfo.Extension.Length);

		//
		if (string.IsNullOrWhiteSpace(destinationdirectory))
		{
			destinationdirectory = directory + filename + @"\";
		}
                    else{
                        destinationdirectory = destinationdirectory + (destinationdirectory.EndsWith(@"\") ? "" : @"\") + filename + @"\";

            if (!Directory.Exists(destinationdirectory))
            {
                Directory.CreateDirectory(destinationdirectory);
            }}
		try
		{
			//
			if (!Directory.Exists(destinationdirectory))
			{
				Directory.CreateDirectory(destinationdirectory);
			}

			//
			using (FileStream zipFileStream = File.OpenRead(zipfilepath))
			{
				using (ZipInputStream zipInputStream = new ZipInputStream(zipFileStream))
				{
					zipInputStream.Password = password;

					ZipEntry zipEntry;
					while ((zipEntry = zipInputStream.GetNextEntry()) != null)
					{
						//如果是文件夹则创建
						if (zipEntry.IsDirectory)
						{
							Directory.CreateDirectory(Path.Combine(destinationdirectory, Path.GetDirectoryName(zipEntry.Name)));
						}
						//如果是文件则创建
						else
						{
							string fileName = Path.GetFileName(zipEntry.Name);
							if (!string.IsNullOrEmpty(fileName) && fileName.Trim().Length > 0)
							{
								FileInfo fileInfo = new FileInfo(Path.Combine(destinationdirectory, zipEntry.Name));

								using (FileStream fileStream = fileInfo.Create())
								{
									byte[] buffer = new byte[BufferSize];
									int read = 0;
									while ((read = zipInputStream.Read(buffer, 0, BufferSize)) > 0)
									{
										fileStream.Write(buffer, 0, read);
									}

									//
									fileStream.Flush();
								}

								//
								fileInfo.LastWriteTime = zipEntry.DateTime;
							}
						}
					}
				}
			}

			//
			result = destinationdirectory;
		}
		catch (System.Exception ex)
		{
			if (Directory.Exists(destinationdirectory))
			{
				Directory.Delete(destinationdirectory, true);
			}

			throw new Exception("解压缩发生错误!", ex);
		}

		return result;
	}
	
	public static string CompressAdd(string zipfilepath, IEnumerable<string> sourcepathlist, string zipdirpath = null, string password = null)
    {
        string result = null;

        try
        {
            //
            if (string.IsNullOrWhiteSpace(zipfilepath))
            {
                throw new Exception("压缩文件[{zipfilepath}]不能为空、NULL或空白字符!");
            }
            //
            if (!File.Exists(zipfilepath))
            {
                throw new FileNotFoundException($"压缩文件[{zipfilepath}]在存储设备上不存在!");
            }

            //
            if (sourcepathlist == null || !(sourcepathlist.Count() > 0))
            {
                throw new Exception("待添加到压缩包的全路径文件或文件夹列表不能为空、NULL或空白字符!");
            }
            //
            foreach (string sourcepath in sourcepathlist)
            {
                if (string.IsNullOrWhiteSpace(sourcepath))
                {
                    throw new Exception("待添加到压缩包的全路径文件或文件夹列表中的元素不能为空、NULL或空白字符!");
                }

                if (!(File.Exists(sourcepath) || Directory.Exists(sourcepath)))
                {
                    throw new Exception($"待添加到压缩包的全路径文件或文件夹列表中元素[{sourcepath}]在存储设备上不存在!");
                }
            }

            //
            if (string.IsNullOrWhiteSpace(zipdirpath))
            {
                zipdirpath = null;
            }
            else
            {
                if (!zipdirpath.EndsWith(@"/"))
                {
                    zipdirpath = zipdirpath + @"/";
                }
            }

            //获取文件、文件夹列表
            List<FileEntry> fileEntryList = GetFileEntry(sourcepathlist);

            //将文件添加到已有zip文件中
            using (ZipFile zip = new ZipFile(zipfilepath))
            {
                //当前添加文件的密码,一个ZIP中,不同文件可以设置不同的密码
                //zip.Password = password;
                //更新压缩档的注释(全局)
                //zip.SetComment("1");

                zip.BeginUpdate();

                foreach (FileEntry fileEntry in fileEntryList)
                {
                    if (fileEntry.IsDirectory)
                    {
                        //zip.Add(new ZipEntry((zipdirpath != null ? zipdirpath : "") + fileEntry.ZipEntryName + @"/") { Size = 0, CompressedSize = 0, CompressionMethod = CompressionMethod.Deflated });
                        zip.AddDirectory((zipdirpath != null ? zipdirpath : "") + fileEntry.ZipEntryName + @"/");
                    }
                    else
                    {
                        //zip.Add(fileEntry.FullName, (zipdirpath != null ? zipdirpath : "") + fileEntry.ZipEntryName);
                        zip.Add(new StaticDataSource(fileEntry.FullName), new ZipEntry((zipdirpath != null ? zipdirpath : "") + fileEntry.ZipEntryName) { DateTime = fileEntry.LastWriteTime, Size = fileEntry.Length, CompressionMethod = CompressionMethod.Deflated });
                    }
                }
                zip.CommitUpdate();
            }

            //
            result = zipfilepath;
        }
        catch (System.Exception ex)
        {
            throw new Exception("压缩包添加文件失败!", ex);
        }

        return result;
    }
}

}

string[] filepaths = new string[] { @"C:\bill\d0d76d40-617b-496a-81e5-3105eae7b723.jpg", @"C:\bill\caf4e9b1-0232-4f0e-bf57-d31396ea73e9.jpg", @"C:\bill\tttt", @"C:\ball" };

Step 2: string zip = SoluM.Utils.Zip.ZipHelper.Compress(filepaths, null, "11111111111111", "123456"); Process.Start("explorer.exe", "/select, " + zip); string dezip = SoluM.Utils.Zip.ZipHelper.Decomparess(zip, @"C:\zipDe", "123456");

Step 3: string zip2 = SoluM.Utils.Zip.ZipHelper.CompressAdd(zippath3, new string[] { @"C:\bill\培训签到1.jpg", @"C:\bill\培训签到2.jpg", @"C:\bill\培训签到3.jpg", @"C:\HP_LaserJet_Pro_MFP_M426-M427" }, @"ball/1/2/", null);

Step 4: SoluM.Utils.Zip.ZipHelper.Decomparess(zip2, null, "123456"); --Here,while ((zipEntry = zipInputStream.GetNextEntry()) != null),throw “Stored, but compressed != uncompressed”

Expected behavior

Fix the bug。

Operating System

Windows

Framework Version

.NET Framework 4.x

Tags

ZIP

Additional context

No response

Luohui109 avatar Nov 14 '24 06:11 Luohui109