How to know which rar is first in multi rar archives using SevenZipSharp/Unrar in C#?

被刻印的时光 ゝ 提交于 2019-12-04 14:36:02

I believe that you could use SevenZipExtractor.ArchiveFileData property and then iterate through header data to find the relevant information.

Part of the RAR header structure :

HEAD_FLAGS Bit flags: 2 bytes

            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

Edit :

When I downloaded SevenZipSharp(1 hour ago) and found that SevenZipExtractor class contains a property that lists every file in volume (VolumeFileNames). I thought 'Great! That was easy!', well... it's never that easy. It seems that VolumeFileNames works perfectly but only if you point it to the first rar in volume :(

The wokraround :

I've created a method to guess and verify the first volume :

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

It's quick&dirty but works and you can refine it further according to your needs.

I hope this helps.

Using SharpCompress

using (var archive = RarArchive.Open("Rar.multi.part01.rar")))
{
    Assert.IsTrue(archive.IsMultipartVolume());
    Assert.IsTrue(archive.IsFirstVolume());
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!