Почему мой SharpZipLib ZipEntry.Comment не устанавливается (или не читается)?

Я работал над инструментом, который использует SharpZipLib для добавления файлов в zip-файл, с комментарием к ZipEntry для хранения части метаданных мне нужно. (Я знаю, что есть другие способы обработки этих метаданных, но я бы хотел избежать повторной архитектуры своего решения, если смогу избежать этого.)

[Слегка упрощенный] код, используемый для записи файла и метаданных в zipfile, выглядит так:

public static void AddFileToZip(string path, Guid metadata)
{
    using (ZipFile zipFile = new ZipFile(__zipName))
    {
        zipFile.BeginUpdate();
        zipFile.Add(path);
        zipFile.CommitUpdate();
        zipFile.Close();
    }
    // Close and reopen the ZipFile so it can find the ZipEntry:
    using (ZipFile zipFile = new ZipFile(__zipName))
    {
        string cleanPath = ZipEntry.CleanName(path);
        zipFile.BeginUpdate();
        zipFile.GetEntry(cleanPath).Comment = metadata.ToString("N");
        zipFile.CommitUpdate();
        zipFile.Close();
    }
}

Испытательный жгут для этого, затем гласит:

[Test]
public void ArchiveCreationTests()
{
    // Hard-code some variables
    string testFile = @"C:\Users\owen.blacker\Pictures\Ddraig arian.png";
    Guid guid = Guid.NewGuid();

    MyClassName.AddFileToZip(testFile, guid);
    Assert.IsTrue(File.Exists(__zipName), "File does not exist: " + __zipName);

    string cleanName = ZipEntry.CleanName(testFile);
    ZipFile zipfile = new ZipFile(__zipName);
    Assert.GreaterOrEqual(
        zipfile.FindEntry(cleanName, true),
        0,
        "Cannot file ZipEntry " + cleanName);

    ZipEntry zipEntry = zipfile.GetEntry(cleanName);
    StringAssert.AreEqualIgnoringCase(
        guid.ToString("N"),
        zipEntry.Comment,
        "Cannot validate GUID comment.");
}

Сейчас создается мой zip-файл, и он действительно содержит мое тестовое изображение. Ddraig arian.png -, ZipEntry успешно найден, но StringAssert звонок всегда терпит неудачу. Я не совсем уверен, что это сбой, потому что он не записывается, или если он терпит неудачу, потому что он не читается.

Теперь я знаю, что вы должны использовать ZipFile / ZipEntry чтобы получить доступ к ZipEntry.Comment, как ZipInputStream не позволяет вам добраться до Comment, но я использую ZipFile а также ZipEntry Я не понимаю, почему это не сработает.

У кого-нибудь есть какие-либо идеи?

(Немного странно закрыть и открыть в AddFileToZip потому что ZipFile.GetEntry звонок всегда терпел неудачу, по-видимому, потому что ZipEntry еще не был записан в индекс файла. И да, мой тестовый файл действительно серебряный дракон.)

3 ответа

Решение

Сможете ли вы использовать DotNetZip? Мне легче использовать большую часть времени, я смог заставить работать комментарии ZipEntry, см. Ниже.

Используя DotNetZip:

using (ZipFile zip = new ZipFile(__zipName))
{
    string testFile = @"...";
    ZipEntry newEntry = zip.AddFile(testFile);
    newEntry.Comment = "test";
    zip.Save();
}
using (ZipFile zip = new ZipFile(__zipName))
{
    Console.WriteLine(zip[0].Comment);
}

Похоже, что SharpZipLib не полностью поддерживает ZipEntry.Commentсм. ответ @DRMacIver для хорошего исследования там, я также попробовал многократные способы и не могу понять это (я могу установить комментарий и сохранить, но когда я читаю это снова, это - ноль).

Я не знаю, почему это не работает, но я предполагаю, что это может быть потому, что стандартные zifiles не поддерживают комментарии для файлов, только один комментарий для всего zip-файла. Так что я думаю, что они могут расширять zip для поддержки этого, возможно, они никогда не заканчивали это или никогда не проверяли это

Не имеет значения, но я упомяну, что ранее я проводил тесты, и SharpZipLib смог добиться немного лучшего сжатия, но простота использования DotNetZip все же сделала его лучшим решением для меня.

Я не пробовал использовать SharpZipLib для чтения zip-файла, созданного с помощью DotNetZip, с рабочими комментариями, чтобы выяснить, могут ли быть проблемы с его чтением или записью (мне интересно об этом)

Да, это не сработает, насколько я могу судить. Комментарий не пишется и не будет содержать текущую итерацию библиотеки.

Я вообще не использовал эту библиотеку, но делаю некоторую проверку исходного кода:

Если мы посмотрим здесь в исходном коде, то увидим, что он запускает только обновления, если contentsEdited. Хм. Интересно, что это устанавливает? Кажется вероятным виновником.

При поиске мы находим следующий подозрительный комментарий к некоторому закомментированному коду

/* Modify not yet ready for public consumption.
   Direct modification of an entry should not overwrite original data before its read.

И, как правило, при поиске в исходном коде мы находим много недоделанного мусора вокруг модификации записей.

В общем, я думаю, что вы напали на половину готовой библиотеки, которая не делает то, что вы хотите. Сожалею.:-)

Некоторая дополнительная археология кода не показывает мне способа написания комментария при первом добавлении файла, увы. Возможно, можно что-то взломать, выловив объект ZipEntry до того, как вы передадите обновление, но как это ускользает от меня.

Код общедоступный, нужно только изменить это... в строке File ZipFile.cs (для меня 1810)

Этот пример для IStaticDataSource ... для другого метода измените другие методы:)

/// <summary>
/// Add a file entry with data.
/// </summary>
/// <param name="dataSource">The source of the data for this entry.</param>
/// <param name="entryName">The name to give to the entry.</param>
/// <param name="compressionMethod">The compression method to use.</param>
/// <param name="useUnicodeText">Ensure Unicode used for name/comments for this entry.</param>
/// <param name="comment">Comentario</param>
public void Add(IStaticDataSource dataSource, string entryName,
    CompressionMethod compressionMethod, bool useUnicodeText, string comment)
{
    if (dataSource == null)
    {
        throw new ArgumentNullException("dataSource");
    }

    if (entryName == null)
    {
        throw new ArgumentNullException("entryName");
    }

    CheckUpdating();

    ZipEntry entry = EntryFactory.MakeFileEntry(entryName, false);
    entry.IsUnicodeText = useUnicodeText;
    entry.CompressionMethod = compressionMethod;
    entry.Comment = comment;

    AddUpdate(new ZipUpdate(dataSource, entry));
}
Другие вопросы по тегам