当尝试提取 .jar 文件时,我不断收到:
提取存档条目将创建一个位于指定目标目录之外的文件
有人可以帮助我吗?这是我的代码:
try
{
using (ZipArchive archive = ZipFile.Open(jarLocationTXT.Text, ZipArchiveMode.Update))
{
archive.ExtractToDirectory(@"C:\Users\Neglekt\Monix Software\MCMI\CurExtract\");
}
}
catch (IOException ExtrEx)
{
MessageBox.Show(ExtrEx.ToString());
MessageBox.Show("An error occured while processing your data! \n Error code: E:002", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
如果创建 ZipArchiveEntry 时在文件路径开头使用了额外的 \,ZipFile.ExtractToDirectory 会认为文件路径位于 zip 文件之外。
ok: ZipArchiveEntry.CreateEntry("文件夹 ile.ext");
不行:ZipArchiveEntry.CreateEntry("older ile.ext"); 当使用 7zip 之类的工具打开 zip 包时,文件路径不正确,在图形用户界面中看起来类似于 _ old ile.ext。
文档说,在以下情况下会抛出这样的异常:
例如,条目名称包含父目录访问器。
父目录访问器例如是
..
。当您在命令提示符下键入 cd ..
时,您是在告诉 change directory (cd
) 程序转到父目录,这就是 ..
的含义。因此会抛出异常,因为 zip 文件中的条目包含对某个父目录的引用。
在使用
ExtractToDirectory
时,似乎没有办法绕过该检查,因此一个选项是使用静态或扩展方法来滚动您自己的提取方法。我的意思是创建一个你自己的方法:
ZipArchive
中打开文件。Entries
ZipArchiveEntry
提取到文件中。 ZipFile.ExtractToDirectory
将失败 /
请使用下面的
ZipFileEx.ExtractToDirectory
来代替:
namespace System.IO.Compression {
public static class ZipFileEx {
public static void ExtractToDirectory(string sourceArchiveFileName, string destinationDirectoryName) =>
ExtractToDirectory(sourceArchiveFileName, destinationDirectoryName, entryNameEncoding: null, overwriteFiles: false);
public static void ExtractToDirectory(string sourceArchiveFileName, string destinationDirectoryName, bool overwriteFiles) =>
ExtractToDirectory(sourceArchiveFileName, destinationDirectoryName, entryNameEncoding: null, overwriteFiles: overwriteFiles);
public static void ExtractToDirectory(string sourceArchiveFileName, string destinationDirectoryName, Encoding? entryNameEncoding) =>
ExtractToDirectory(sourceArchiveFileName, destinationDirectoryName, entryNameEncoding: entryNameEncoding, overwriteFiles: false);
public static void ExtractToDirectory(string sourceArchiveFileName, string destinationDirectoryName, Encoding? entryNameEncoding, bool overwriteFiles)
{
ArgumentNullException.ThrowIfNull(sourceArchiveFileName);
ArgumentNullException.ThrowIfNull(destinationDirectoryName);
using ZipArchive archive = ZipFile.Open(sourceArchiveFileName, ZipArchiveMode.Read, entryNameEncoding);
foreach (ZipArchiveEntry entry in archive.Entries) {
DirectoryInfo di = Directory.CreateDirectory(destinationDirectoryName);
string destinationDirectoryFullPath = di.FullName;
if (!destinationDirectoryFullPath.EndsWith(Path.DirectorySeparatorChar)) {
char sep = Path.DirectorySeparatorChar;
destinationDirectoryFullPath = string.Concat(destinationDirectoryFullPath, new ReadOnlySpan<char>(in sep));
}
string entryFullName = entry.FullName;
if (entryFullName.Length > 0 && entryFullName[0] == '/') entryFullName = entryFullName[1..]; // remove leading root
string fileDestinationPath = Path.GetFullPath(Path.Combine(destinationDirectoryFullPath, entryFullName.Replace('\0', '_')));
var IsCaseSensitive = !(OperatingSystem.IsWindows() || OperatingSystem.IsMacOS() || OperatingSystem.IsIOS() || OperatingSystem.IsTvOS() || OperatingSystem.IsWatchOS());
var stringComparison = IsCaseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase;
if (!fileDestinationPath.StartsWith(destinationDirectoryFullPath,stringComparison)) throw new IOException(@"Extracting Zip entry would have resulted in a file outside the specified destination directory.");
if (Path.GetFileName(fileDestinationPath).Length == 0) {
if (entry.Length != 0) throw new IOException(@"Zip entry name ends in directory separator character but contains data.");
Directory.CreateDirectory(fileDestinationPath);
} else {
Directory.CreateDirectory(Path.GetDirectoryName(fileDestinationPath)!);
entry.ExtractToFile(fileDestinationPath, overwrite: overwriteFiles);
}
}
}
}
}
上面是
ZipFile.ExtractToDirectory
的精确副本,除了检查 entryFullName[0] == '/'
的行之外