Как узнать, какой rar является первым в архивах с несколькими rar, используя SevenZipSharp/Unrar в C#?

Я пытаюсь использовать библиотеку SevenZipSharp и/или Unrar в C# WinForms .NET 3.5. У меня есть эта проблема с несколькими архивами rar, которые имеют разные имена, например:

  • .rar, r01, r02, r03 и так далее (это легко)
  • какой-то файл01.rar, какой-то файл02.rar, какой-то файл03.rar

  • .001, .002, 003 и так далее.

Если я укажу Unrar или SevenZipSharp на неправильный архив, он распакует этот конкретный архив, а остальные останутся нераспакованными. Так что я должен указать правильный (если я не делаю что-то не так).

Как лучше всего это проверить? На данный момент я проверяю, есть ли в каталоге более одного файла .rar, и если да, то я проверяю наличие 01.rar. Если есть только один и .rar и пара r01, то я получаю .rar, но это кажется немного неправильным.

Есть ли способ заставить SevenZip или Unrar фактически распаковывать весь мульти-RAR-пакет, просто указав на любой файл .rar? или .001 ?

Сумасшедший мальчик

РЕДАКТИРОВАТЬ:

Я попытался использовать следующий код, чтобы получить информацию, предложенную в одном ответе, но он не смог предоставить обещанную информацию. extr.ArchiveFileData возвращает 0 для zip и 32 для любого предоставленного rar, будь то rar или r01.

        using (SevenZipExtractor extr = new SevenZipExtractor(fileName)) {

            foreach (var var in  extr.ArchiveProperties) {
                string attributes = var.Name;
                object test = var.Value;
                if (test == null) {
                    test = "THIS";
                } 
                MessageBox.Show(attributes.ToString(), test.ToString());
            }
                            foreach (var var in extr.ArchiveFileData) {
               MessageBox.Show(var.Attributes.ToString());
            }
        }

person MadBoy    schedule 23.02.2010    source источник


Ответы (2)


Я считаю, что вы могли бы использовать свойство SevenZipExtractor.ArchiveFileData, а затем перебирать данные заголовка, чтобы найти соответствующую информацию.

Часть структуры заголовка RAR:

HEAD_FLAGS Битовые флаги: 2 байта

            0x0001  - Volume attribute (archive volume)
            0x0002  - Archive comment present
                      RAR 3.x uses the separate comment block
                      and does not set this flag.

            0x0004  - Archive lock attribute
            0x0008  - Solid attribute (solid archive)
            0x0010  - New volume naming scheme (\'volname.partN.rar\')
            0x0020  - Authenticity information present
                      RAR 3.x does not set this flag.

            0x0040  - Recovery record present
            0x0080  - Block headers are encrypted
            0x0100  - First volume (set only by RAR 3.0 and later)

            other bits in HEAD_FLAGS are reserved for
            internal use

Изменить:

Когда я скачал SevenZipSharp (1 час назад) и обнаружил, что класс SevenZipExtractor содержит свойство, в котором перечислены все файлы в томе (VolumeFileNames). Я подумал: «Отлично! Это было легко!», ну... это никогда не бывает так просто. Вроде VolumeFileNames работает отлично, но только если указать на первый по объему рар :(

Раунд:

Я создал метод угадывания и проверки первого тома:

private static string LocateFirstVolume(string filename)
{
    var isVolume = false;
    var parts = 1u;

    using (var extractor = new SevenZipExtractor(filename))
    {
        isVolume =
            extractor.ArchiveProperties.Any(x =>
                x.Name.Equals("IsVolume") && x.Value.Equals(true));

        parts = (
            from x in extractor.ArchiveProperties
            where x.Name.Equals("Number of volumes")
            select (uint)x.Value).DefaultIfEmpty(1u).SingleOrDefault();
    }

    if (!isVolume)
        return null;

    if (parts > 1)
        return filename;

    if (!Path.GetExtension(filename)
        .Equals(".rar", StringComparison.OrdinalIgnoreCase))
    {
        var rarFile = 
            Path.Combine(
                Path.GetDirectoryName(filename), 
                Path.GetFileNameWithoutExtension(filename) + ".rar");

        if (File.Exists(rarFile))
        {
            var firstVolume = LocateFirstVolume(rarFile);

            if (firstVolume != null)
            {
                return firstVolume;
            }
        }
    }

    var directoryFiles = Directory.GetFiles(Path.GetDirectoryName(filename));

    foreach (var directoryFile in directoryFiles)
    {
        var firstVolume = LocateFirstVolume(directoryFile);

        if (firstVolume != null)
        {
            using (var extractor = new SevenZipExtractor(firstVolume))
            {
                if (extractor.VolumeFileNames.Contains(filename))
                {
                    return firstVolume;
                }
            }
        }
    }

    return null;
}

Это быстро и грязно, но работает, и вы можете усовершенствовать его в соответствии со своими потребностями.

Надеюсь, это поможет.

person Diadistis    schedule 23.02.2010
comment
Есть ли такая же информация в Unrar.dll, по какой-то причине я не смог заставить библиотеку SevenZip распаковать упакованные архивы 001, 002 (не знаю почему). Возможно, новая версия исправила это, но не было времени проверить. - person MadBoy; 23.02.2010
comment
Я уверен, что информация доступна с помощью unrar.dll, методов RARReadHeader и RARReadHeaderEx, но я больше ничего не знаю по этому вопросу. - person Diadistis; 23.02.2010
comment
Пожалуйста, проверьте обновленный вопрос, в котором указано, какой код я использовал и какие результаты я получаю, похоже, не работает:/ - person MadBoy; 23.02.2010

Использование SharpCompress

using (var archive = RarArchive.Open("Rar.multi.part01.rar")))
{
    Assert.IsTrue(archive.IsMultipartVolume());
    Assert.IsTrue(archive.IsFirstVolume());
}
person adamhathcock    schedule 28.09.2011
comment
Хороший. Спасибо, посмотрим, как пойдет. - person MadBoy; 28.09.2011