Как проверить, что файлы, сжатые из нескольких частей (например, 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;
}

Я не уверен, что это то, что вы ищете, или вам нужны более подробные сведения об ошибке. Но надеюсь, что это поможет вам решить вашу проблему.

Другие вопросы по тегам