3

我正在尝试在 C# WinForms .NET 3.5 中使用 SevenZipSharp 或/和 Unrar 库。我对具有不同命名的多 rar 档案有这个问题,例如:

  • .rar, r01, r02, r03 等等(这个很简单)
  • somefile01.rar, somefile02.rar, somefile03.rar

  • .001、.002、003 等等。

如果我将 Unrar 或 SevenZipSharp 指向错误的存档,它将解压该特定存档并让其余部分解压。所以我必须指出正确的(除非我做错了什么)。

最好的检查方法是什么?现在我正在检查目录中是否有多个 .rar 文件,如果有,我检查 01.rar。如果只有一个 .rar 和几个 r01 ,那么我会得到 .rar ,但这似乎有点错误。

有没有办法让 SevenZip 或 Unrar 仅通过指向任何 .rar 文件来实际解压缩整个多 rar 包?或 .001 ?

愤怒的少年

编辑:

我尝试使用以下代码来获取一个答案中建议的信息,但它未能提供承诺的信息。extr.ArchiveFileData 对于 zip 返回 0,对于任何提供的 rar(无论是 rar 还是 r01)返回 32。

        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());
            }
        }
4

2 回答 2

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效果很好,但前提是您将其指向卷中的第一个 rar :(

解决方法:

我创建了一种猜测和验证第一卷的方法:

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

它又快又脏,但可以工作,您可以根据需要进一步改进它。

我希望这有帮助。

于 2010-02-23T10:53:38.857 回答
1

使用SharpCompress

using (var archive = RarArchive.Open("Rar.multi.part01.rar")))
{
    Assert.IsTrue(archive.IsMultipartVolume());
    Assert.IsTrue(archive.IsFirstVolume());
}
于 2011-09-28T12:15:52.180 回答