Как узнать, какой 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 фактически распаковывать весь пакет multi 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());
}
}
Решение
Я считаю, что вы могли бы использовать 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;
}
Это быстро и грязно, но работает, и вы можете доработать его в соответствии со своими потребностями.
Надеюсь, это поможет.
Другие советы
С использованием SharpCompress
using (var archive = RarArchive.Open("Rar.multi.part01.rar")))
{
Assert.IsTrue(archive.IsMultipartVolume());
Assert.IsTrue(archive.IsFirstVolume());
}