C# 在使用 System.IO.Compression 提取文件期间强制替换现有文件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14795197/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Forcefully Replacing Existing Files during Extracting File using System.IO.Compression?
提问by user960567
I am using the following code to extract all files in a folder
我正在使用以下代码提取文件夹中的所有文件
using (ZipArchive archive = new ZipArchive(zipStream))
{
archive.ExtractToDirectory(location);
}
But if one file exist then it throws an exception. Is there is any way to tell the Compression API to replace the existing files.
但如果存在一个文件,则会引发异常。有什么方法可以告诉压缩 API 替换现有文件。
I found one way is to get all the file names first then check whether file exist and delete it. But this is somehow very costly for me.
我发现一种方法是先获取所有文件名,然后检查文件是否存在并删除它。但这对我来说是非常昂贵的。
采纳答案by user960567
I have created an extension. any comment to it improve will be appreciated,
我已经创建了一个扩展。对其改进的任何评论将不胜感激,
public static class ZipArchiveExtensions
{
public static void ExtractToDirectory(this ZipArchive archive, string destinationDirectoryName, bool overwrite)
{
if (!overwrite)
{
archive.ExtractToDirectory(destinationDirectoryName);
return;
}
DirectoryInfo di = Directory.CreateDirectory(destinationDirectoryName);
string destinationDirectoryFullPath = di.FullName;
foreach (ZipArchiveEntry file in archive.Entries)
{
string completeFileName = Path.GetFullPath(Path.Combine(destinationDirectoryFullPath, file.FullName));
if (!completeFileName.StartsWith(destinationDirectoryFullPath, StringComparison.OrdinalIgnoreCase))
{
throw new IOException("Trying to extract file outside of destination directory. See this link for more info: https://snyk.io/research/zip-slip-vulnerability");
}
if (file.Name == "")
{// Assuming Empty for Directory
Directory.CreateDirectory(Path.GetDirectoryName(completeFileName));
continue;
}
file.ExtractToFile(completeFileName, true);
}
}
}
回答by Victor RENé
Take a look at this: Creating zip files easily in .NET 4.5. Your problem seems to be adressed. Alternatively, you can also check DotNetZip.
看看这个:在 .NET 4.5 中轻松创建 zip 文件。您的问题似乎已得到解决。或者,您也可以检查DotNetZip。
回答by Gregory Nozik
You can extract files to some temp directory and than copy files with the "File.Copy" with the ovveride option true to your destination directory
您可以将文件解压缩到某个临时目录,然后使用“File.Copy”和 ovveride 选项将文件复制到您的目标目录
I know that it's not a perfect solution , but this way you do not need to check if file exist
我知道这不是一个完美的解决方案,但是这样您就不需要检查文件是否存在
回答by Mohy66
This code will not throw exception when the folder is not exist, instead of that it will create the folder.
当文件夹不存在时,此代码不会抛出异常,而是会创建文件夹。
public static class ZipArchiveExtensions
{
public static void ExtractToDirectory(this ZipArchive archive, string destinationDirectoryName, bool overwrite)
{
if (!overwrite)
{
archive.ExtractToDirectory(destinationDirectoryName);
return;
}
foreach (ZipArchiveEntry file in archive.Entries)
{
string completeFileName = Path.Combine(destinationDirectoryName, file.FullName);
string directory = Path.GetDirectoryName(completeFileName);
if (!Directory.Exists(directory))
Directory.CreateDirectory(directory);
if (file.Name != "")
file.ExtractToFile(completeFileName, true);
}
}
}
回答by Александр Пекшев
A little remade method from the answer to create all the folders
从答案中重新制作的一些方法来创建所有文件夹
public static void ExtractToDirectory(this ZipArchive archive, string destinationDirectoryName, bool overwrite)
{
if (!overwrite)
{
archive.ExtractToDirectory(destinationDirectoryName);
return;
}
foreach (ZipArchiveEntry file in archive.Entries)
{
string completeFileName = Path.Combine(destinationDirectoryName, file.FullName);
if (file.Name == "")
{// Assuming Empty for Directory
Directory.CreateDirectory(Path.GetDirectoryName(completeFileName));
continue;
}
// create dirs
var dirToCreate = destinationDirectoryName;
for (var i = 0; i < file.FullName.Split('/').Length - 1; i++)
{
var s = file.FullName.Split('/')[i];
dirToCreate = Path.Combine(dirToCreate, s);
if (!Directory.Exists(dirToCreate))
Directory.CreateDirectory(dirToCreate);
}
file.ExtractToFile(completeFileName, true);
}
}
回答by FastHyman
As I'm a total Linq fan, the Linq-ish way just for reference:
由于我是 Linq 的忠实粉丝,Linq-ish 方式仅供参考:
using (var strm = File.OpenRead(zipPath))
using (ZipArchive a = new ZipArchive(strm))
{
a.Entries.Where(o => o.Name == string.Empty && !Directory.Exists(Path.Combine(basePath, o.FullName))).ToList().ForEach(o => Directory.CreateDirectory(Path.Combine(basePath, o.FullName)));
a.Entries.Where(o => o.Name != string.Empty).ToList().ForEach(e => e.ExtractToFile(Path.Combine(basePath, e.FullName), true));
}
回答by Riccardo Bassilichi
This is useful when you have zip file path
当您有 zip 文件路径时,这很有用
public static class ZipArchiveHelper
{
public static void ExtractToDirectory(string archiveFileName, string destinationDirectoryName, bool overwrite)
{
if (!overwrite)
{
ZipFile.ExtractToDirectory(archiveFileName, destinationDirectoryName);
}
else
{
using (var archive = ZipFile.OpenRead(archiveFileName))
{
foreach (var file in archive.Entries)
{
var completeFileName = Path.Combine(destinationDirectoryName, file.FullName);
var directory = Path.GetDirectoryName(completeFileName);
if (!Directory.Exists(directory) && !string.IsNullOrEmpty(directory))
Directory.CreateDirectory(directory);
if (file.Name != "")
file.ExtractToFile(completeFileName, true);
}
}
}
}
}
回答by Mystogan
Hi I'm using DotNetZip download from nugget. I just simply use this code. This will auto replace the files in the directory if exists. "OverwriteSilently" !
您好,我正在使用从 nugget 下载的 DotNetZip。我只是简单地使用这个代码。如果存在,这将自动替换目录中的文件。“无声覆盖”!
using (ZipFile archive = new ZipFile(@"" + System.Environment.CurrentDirectory + "\thezipfile.zip"))
{
archive.ExtractAll(@"" + System.Environment.CurrentDirectory, ExtractExistingFileAction.OverwriteSilently);
}
回答by Neil B
Here is a method that takes a path to the zip file.
这是一个获取 zip 文件路径的方法。
Based on the accepted answer.
基于接受的答案。
public void ExtractZipFileToDirectory(string sourceZipFilePath, string destinationDirectoryName, bool overwrite)
{
using (var archive = ZipFile.Open(sourceZipFilePath, ZipArchiveMode.Read))
{
if (!overwrite)
{
archive.ExtractToDirectory(destinationDirectoryName);
return;
}
DirectoryInfo di = Directory.CreateDirectory(destinationDirectoryName);
string destinationDirectoryFullPath = di.FullName;
foreach (ZipArchiveEntry file in archive.Entries)
{
string completeFileName = Path.GetFullPath(Path.Combine(destinationDirectoryFullPath, file.FullName));
if (!completeFileName.StartsWith(destinationDirectoryFullPath, StringComparison.OrdinalIgnoreCase))
{
throw new IOException("Trying to extract file outside of destination directory. See this link for more info: https://snyk.io/research/zip-slip-vulnerability");
}
if (file.Name == "")
{// Assuming Empty for Directory
Directory.CreateDirectory(Path.GetDirectoryName(completeFileName));
continue;
}
file.ExtractToFile(completeFileName, true);
}
}
}
回答by user2246236
It's as easy as setting a overwriteFiles to true in: ZipFile.ExtractToDirectory(string sourceFile, string destDir, Encoding entryNameEncoding, bool overwriteFiles)
就像将 overwriteFiles 设置为 true 一样简单:ZipFile.ExtractToDirectory(string sourceFile, string destDir, Encoding entryNameEncoding, bool overwriteFiles)
Example:
ZipFile.ExtractToDirectory("c:\file.zip","c:\destination_folder", Encoding.UTF8, true);