Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

Add folder, unable to decompress

オープン
#883 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
25/100
issue の種類
バグ
明瞭さ
説明が足りない
活発さ
停滞
技術スタック
csharp
領域
backend

調査の方向性

まず、提供された C# の Compress メソッドと Decomparess メソッドを SharpZipLib 1.3.3 を使った最小限の再現コードに縮小し、ディレクトリエントリ周辺の ZipOutputStream および ZipInputStream の呼び出しに焦点を当てます。“Stored, but compressed != uncompressed”を生成する正確なアーカイブ内容と操作を確認します。完了条件は、再現可能な失敗と、フォルダーの追加および展開について検証済みの動作が得られることです。

索引モデルが issue の本文から書いたものです。

説明

bug zip
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

主要言語
C#
スター
3.9k
フォーク
1k
PR マージ指標
30日以内にマージされた PR はありません

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

icsharpcode/SharpZipLib のほかの issue

icsharpcode/SharpZipLib の issue をすべて見る

似ている issue

C# の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。