C# UnauthorizedAccessException при использовании ZipArchive, но не ZipFile
Я могу заархивировать файлы из определенной папки, используя ZipFile.CreateFromDirectory
в следующем тестовом коде (я использовал этот код только для проверки работы архива):
// Where the files are located
string strStartPath = txtTargetFolder.Text;
// Where the zip file will be placed
string strZipPath = @"C:\Users\smelmo\Desktop\testFinish\" + strFileNameRoot + "_" + txtDateRange1.Text.Replace(@"/", "_") + "_" + txtDateRange2.Text.Replace(@"/", "_") + ".zip";
ZipFile.CreateFromDirectory(strStartPath, strZipPath);
Однако это объединяет ВСЕ содержимое папки. Я пытаюсь сжать определенные элементы в папке, используя ZipArchive
в следующем коде:
// Where the files are located
string strStartPath = txtTargetFolder.Text;
// Where the zip file will be placed
string strZipPath = @"C:\Users\smelmo\Desktop\testFinish\" + strFileNameRoot + "_" + txtDateRange1.Text.Replace(@"/", "_") + "_" + txtDateRange2.Text.Replace(@"/", "_") + ".zip";
using (ZipArchive archive = ZipFile.OpenRead(strStartPath))
{
foreach (ZipArchiveEntry entry in archive.Entries)
{
if (!(entry.FullName.EndsWith(".TIF", StringComparison.OrdinalIgnoreCase)))
{
entry.ExtractToFile(Path.Combine(strZipPath, entry.FullName));
}
}
}
Это дает ошибку в ZipFile.OpenRead(strStartPath)
, Почему я могу получить доступ к точной папке в первом блоке кода, но не во втором? Или есть более простой способ поиска по папке и архивирования только определенных элементов?
1 ответ
Вы используете библиотеки Zip неправильно
Фактически вы пытаетесь открыть каталог, как если бы это был zip-файл, затем зациклите содержимое этого каталога (который опять-таки фактически является zip-файлом), а затем пытаетесь извлечь каждого члена в отдельный zip-файл.
Вот рабочий пример того, что вы описали, что вы пытаетесь сделать:
string strStartPath = @"PATH TO FILES TO PUT IN ZIP FILE";
string strZipPath = @"PATH TO ZIP FILE";
if (File.Exists(strZipPath))
File.Delete(strZipPath);
using (ZipArchive archive = ZipFile.Open(strZipPath, ZipArchiveMode.Create))
{
foreach (FileInfo file in new DirectoryInfo(strStartPath).GetFiles())
{
if (!(file.FullName.EndsWith(".TIF", StringComparison.OrdinalIgnoreCase)))
{
archive.CreateEntryFromFile(Path.Combine(file.Directory.ToString(), file.Name), file.Name);
}
}
}
Это возьмет все содержимое корневого уровня папки и поместит его в zip-файл. Вам нужно будет реализовать свой собственный способ получения подпапок и их содержимого рекурсивно, но это выходит за рамки этого вопроса.
РЕДАКТИРОВАТЬ: Вот рабочий пример с правильной рекурсией папки для выбора всех файлов даже в подкаталогах
public void ZipFolder()
{
string strStartPath = @"PATH TO FILES TO PUT IN ZIP FILE";
string strZipPath = @"PATH TO ZIP FILE";
if (File.Exists(strZipPath))
File.Delete(strZipPath);
using (ZipArchive archive = ZipFile.Open(strZipPath, ZipArchiveMode.Create))
{
foreach (FileInfo file in RecurseDirectory(strStartPath))
{
if (!(file.FullName.EndsWith(".TIF", StringComparison.OrdinalIgnoreCase)))
{
var destination = Path.Combine(file.DirectoryName, file.Name).Substring(strStartPath.Length + 1);
archive.CreateEntryFromFile(Path.Combine(file.Directory.ToString(), file.Name), destination);
}
}
}
}
public IEnumerable<FileInfo> RecurseDirectory(string path, List<FileInfo> currentData = null)
{
if (currentData == null)
currentData = new List<FileInfo>();
var directory = new DirectoryInfo(path);
foreach (var file in directory.GetFiles())
currentData.Add(file);
foreach (var d in directory.GetDirectories())
RecurseDirectory(d.FullName, currentData);
return currentData;
}