Как проверить, что файлы, сжатые из нескольких частей (например, zip), содержат все части или нет в C#?
Я хочу проверить составные сжатые файлы, такие как Zip, потому что, когда какая-либо часть отсутствует для сжатых файлов, возникает ошибка, но я хочу проверить ее перед извлечением, а другое программное обеспечение создает другую структуру имен.
Я также ссылаюсь на один вопрос, связанный с DotNetZip.
Скриншот ниже взят из программного обеспечения 7z.
А второй скриншот взят из DotNetZip с C#.
Еще одна вещь: я также хочу проверить, что оно также повреждено или не похоже на программное обеспечение 7z. Пожалуйста, ознакомьтесь с моими требованиями на скриншоте ниже.
Пожалуйста, помогите мне с этими проблемами.
2 ответа
Из ваших комментариев я понял, что проблема заключается в том, чтобы идентифицировать файлы (получить список частей, принадлежащих друг другу). Вы можете получить список файлов вроде
List<string> files = System.IO.Directory.EnumerateFiles(@"D:\Zip\ForExtract\multipart\",
"500mbInputData.*", SearchOption.TopDirectoryOnly).OrderBy(x => x).ToList();
или для вашего второго случая
List<string> files = System.IO.Directory.EnumerateFiles(@"D:\Zip\ForExtract\multipart\",
"500mbInputData.zip.*", SearchOption.TopDirectoryOnly).OrderBy(x => x).ToList();
а затем используйте список файлов в своем CombinationStream
. Остальной код будет выглядеть так, как написал Manoj Choudhari. Вы также можете указать путь и имя файла с подстановочными знаками в параметр, поэтому я предлагаю добавить в функцию следующие параметры:
public static bool IsZipValid(string basePath, string fileNameWithWildcard)
{
try
{
List<string> files = System.IO.Directory.EnumerateFiles(
basePath, fileNameWithWildcard,
SearchOption.TopDirectoryOnly).OrderBy(x => x).ToList();
using (var zipFile = // ... rest is as Manoj wrote
и используйте его как:
if (IsZipValid(@"D:\Zip\ForExtract\multipart\", "500mbInputData.*")) { // ... }
или
if (IsZipValid(@"D:\Zip\ForExtract\multipart\", "500mbInputData.zip.*")) { // ... }
Чтобы узнать, какие файлы у вас есть в базовом пути, вы можете написать вспомогательную функцию, например
List<string> getZipFormat(string path)
{
bool filesFound(string basePath, string pattern) => System.IO.Directory.EnumerateFiles(
basePath, pattern, SearchOption.TopDirectoryOnly).Any();
var isTar = filesFound(path, "*.tar.???");
var isZip = filesFound(path, "*.z??");
var is7Zip = filesFound(path, "*.7z.???");
var result = new List<string>();
if (isTar) result.Add("TAR");
if (isZip) result.Add("ZIP");
if (is7Zip) result.Add("7ZIP");
return result;
}
Измените его в соответствии с вашими потребностями - он вернет список строк, содержащих "TAR", "ZIP" или "7ZIP" (или более одного из них), в зависимости от шаблонов, соответствующих файлам в базовом каталоге.
Использование (пример для проверки нескольких форматов zip):
var isValid = true;
var basePath = @"D:\Zip\ForExtract\multipart\";
foreach(var fmt in getZipFormat(basePath))
switch (fmt)
{
case "TAR":
isValid = isValid & IsZipValid(basePath, "500mbInputData.tar.*");
break;
case "ZIP":
isValid = isValid & IsZipValid(basePath, "500mbInputData.zip.*");
break;
case "7ZIP":
isValid = isValid & IsZipValid(basePath, "500mbInputData.7z.*");
break;
default:
break;
}
Примечание. Согласно моим экспериментам, может случиться так, что файлы останутся открытыми, хотя ваша программа завершилась, то есть ваши файлы все равно будут заблокированы при следующем запуске кода. Поэтому я настоятельно рекомендую явно закрыть их, например
var fStreams = files.Select(x =>
new FileStream(x, FileMode.Open) as System.IO.Stream).ToList();
using (var cStream = new CombinationStream(fStreams))
using (var zipFile = new ZipArchive(cStream, ZipArchiveMode.Read))
{
// Do whatever you want...
// ... but ensure you close the files
fStreams.Select(s => { s.Close(); return s; });
};
Я не уверен, сможете ли вы увидеть точную ошибку, показанную на вашем снимке. Но у меня есть код, который может помочь вам определить, читается ли составной файл.
Я использовал Nuget Package CombinationStream.
Конструктор ZipArchive выбрасываетArgumentException
или InvalidDataException
если поток не читается.
Ниже приведен код:
public static bool IsZipValid()
{
try
{
string basePath = @"C:\multi-part-zip\";
List<string> files = new List<string> {
basePath + "somefile.zip.001",
basePath + "somefile.zip.002",
basePath + "somefile.zip.003",
basePath + "somefile.zip.004",
basePath + "somefile.zip.005",
basePath + "somefile.zip.006",
basePath + "somefile.zip.007",
basePath + "somefile.zip.008"
};
using (var zipFile = new ZipArchive(new CombinationStream(files.Select(x => new FileStream(x, FileMode.Open) as Stream).ToList()), ZipArchiveMode.Read))
{
// Do whatever you want
}
}
catch(InvalidDataException ex)
{
return false;
}
return true;
}
Я не уверен, что это то, что вы ищете, или вам нужны более подробные сведения об ошибке. Но надеюсь, что это поможет вам решить вашу проблему.