如何在 C# 中使用 SevenZipSharp/Unrar 知道哪个 rar 是多个 rar 存档中的第一个?

发布于 2024-08-22 18:56:17 字数 1209 浏览 10 评论 0原文

我正在尝试在 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?

MadBoy

编辑:

我尝试使用以下代码来获取一个答案中建议的信息,但它无法提供承诺的信息。 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());
            }
        }

I am trying to use SevenZipSharp or/and Unrar library in C# WinForms .NET 3.5. I have this problem with multi rar archives that have diffrent naming for example:

  • .rar, r01, r02, r03 and so on (this is easy)
  • somefile01.rar, somefile02.rar, somefile03.rar

  • .001, .002, 003 and so on.

If i point Unrar or SevenZipSharp to wrong archive it will unpack that particular archive and leave rest unpacked. So i have to point the right one (unless i am doing something wrong).

What would be the best way to check for that? For now i am checking if there are more then one .rar files inside directory then if so i check for 01.rar. If there's only one and .rar and couple of r01 then i get .rar but this seems a bit wrong.

Is there a way to make SevenZip or Unrar to actually unpack whole multi rar pack just by pointing to any .rar file? or .001 ?

MadBoy

EDIT:

I tried to use following code to get information as suggested in one answer but it fails to deliver promised information. extr.ArchiveFileData returns 0 for zip, and 32 for any provided rar whether it's rar or 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());
            }
        }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

宫墨修音 2024-08-29 18:56:17

我相信您可以使用 SevenZipExtractor.ArchiveFileData 属性,然后迭代标头数据以查找相关信息。

RAR 标头结构的一部分:

HEAD_FLAGS 位标志:2 字节

 0x0001 - 卷属性(存档卷)
            0x0002 - 存在存档评论
                      RAR 3.x 使用单独的注释块
                      并且不设置此标志。

            0x0004 - 存档锁定属性
            0x0008 - 实体属性(实体存档)
            0x0010 - 新卷命名方案(\'volname.partN.rar\')
            0x0020 - 存在真实性信息
                      RAR 3.x 不设置此标志。

            0x0040 - 存在恢复记录
            0x0080 - 块头已加密
            0x0100 - 第一卷(仅由 RAR 3.0 及更高版本设置)

            HEAD_FLAGS 中的其他位保留用于
            内部使用

编辑:

当我下载 SevenZipSharp(1 小时前)时,发现 SevenZipExtractor 类包含一个列出卷中每个文件的属性 (VolumeFileNames )。我想‘太棒了!那很容易!”,嗯……从来没有那么容易。看来 VolumeFileNames 工作得很好,但前提是你将它指向卷中的第一个 rar :(

wokraround :

我创建了一个方法来猜测和验证第一个卷:

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

它快速且肮脏,但有效您可以根据您的需要进一步完善它,

我希望这会有所帮助。

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.

揪着可爱 2024-08-29 18:56:17

使用 SharpCompress

using (var archive = RarArchive.Open("Rar.multi.part01.rar")))
{
    Assert.IsTrue(archive.IsMultipartVolume());
    Assert.IsTrue(archive.IsFirstVolume());
}

Using SharpCompress

using (var archive = RarArchive.Open("Rar.multi.part01.rar")))
{
    Assert.IsTrue(archive.IsMultipartVolume());
    Assert.IsTrue(archive.IsFirstVolume());
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文