Почему мой 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));
}