Как проверить, что многокомпонентные сжатые (т.е. zip) файлы имеют все части или нет в C#? - PullRequest
7 голосов
/ 31 января 2020

Я хочу проверить составные сжатые файлы, такие как Zip, потому что, если какая-либо часть отсутствует для сжатых файлов, возникает ошибка, но я хочу проверить ее перед извлечением, и другое программное обеспечение создает другую структуру имен.

I также обратитесь к одному DotNetZip связанным вопросам.

Ниже приведен скриншот из программного обеспечения 7z.

enter image description here

И второй скриншот взят из DotNetZip из C#.

enter image description here

Еще одна вещь - я также хочу проверить, что он также поврежден или не похож на программное обеспечение 7z , Пожалуйста, обратитесь к скриншоту ниже для моих требований.

enter image description here

Пожалуйста, помогите мне с этими вопросами.

Ответы [ 2 ]

2 голосов
/ 06 февраля 2020

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

Я использовал пакет nuget 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;
}

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

1 голос
/ 11 февраля 2020

Из ваших комментариев я понял, что проблема заключается в том, чтобы идентифицировать файлы (получить список принадлежащих друг другу частей). Вы можете получить список файлов типа

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» (или более одной из них), в зависимости от сопоставления шаблонов с файлами в базовом каталоге.

Использование (пример для проверки нескольких zipformat):

    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; });
    };
...