sharpcompress icon indicating copy to clipboard operation
sharpcompress copied to clipboard

can only get one entry from a zip or rar

Open AnakinSkyCN opened this issue 4 years ago • 2 comments

Hi,

I've tried using MoveToNextEntry to enumerate all the entries in a zip or rar with multiple entries, but it only return one entry then ended.

did I do something wrong?

            using (Stream stream = File.OpenRead(archivefile))
           {
                IReader reader = ReaderFactory.Open(stream);
                try
                {
                    while (reader.MoveToNextEntry())
                    {
                        if (!reader.Entry.IsDirectory)
                        {
                            Console.WriteLine(reader.Entry.Key);
                            EntryStream entryStream = reader.OpenEntryStream();
                            DataSetSampleCase.dtSampleCaseFileRow newrow = dsSampleCase.dtSampleCaseFile.NewdtSampleCaseFileRow();
                            newrow.完整文件路径 = archivefile + @"\\" +  reader.Entry.Key;
                            string purefilename = Func.StringOP.PureFileNameFromFull(reader.Entry.Key);
                            newrow.文件 = purefilename;
                            newrow.时间 = File.GetLastWriteTime(archivefile);
                            string Content = IOFunc.ContentByFileName(reader.Entry.Key);
                            newrow.内容 = Content;
                            dsSampleCase.dtSampleCaseFile.AdddtSampleCaseFileRow(newrow);
                        }
                    }
                }
                catch (Exception err)
                {
                    Debug.WriteLine(err.Message);
                }
            }

AnakinSkyCN avatar May 22 '20 01:05 AnakinSkyCN

The tests have a lot of examples.

Try Disposing the entry stream. You should be putting using blocks on every stream/reader

adamhathcock avatar May 24 '20 07:05 adamhathcock

I'm running into this too. It happens even with using (var entryStream = reader.OpenEntryStream()) to properly dispose it.

using (var zipReader = ReaderFactory.Open(fileStream, new ReaderOptions { Password = privateKey }))
{
    while (zipReader.MoveToNextEntry())
    {
        Console.WriteLine(zipReader.Entry.Key);

        // commenting out the next two lines of code will make the Console.WriteLine above print out ALL entries
        // but leaving them in will make it print only one line.
        using (var entryStream = zipReader.OpenEntryStream())
        using (var streamReader = new StreamReader(entryStream, Encoding.UTF8))
        {
            //...other logic. This block could be empty and still exhibits the issue.
        }
    }
}

Seems to only happen with certain zip files, but unfortunately I'm dealing with data that I can't publish so I can't provide a test case. The affected files I have are password protected. It skips files only when the entry content is accessed via methods like OpenEntryStream() or WriteEntryTo(memStream). If the entry contents is not accessed using those methods, no entries are skipped and the MoveToNextEntry() behavior works perfectly.

Since my zip files were small, I got around this issue with a really dirty and poor performing hack:

  1. Read the zip file once without accessing entry contents, but just adding all entry metadata to a list of IEntry
  2. Recreate the zip reader to read each IEntry's contents, skipping all other entries except the one, matching by IEntry.Key. A fresh zip reader needs to be created for each entry whose contents needs to be read.

hungyiloo avatar Apr 13 '21 06:04 hungyiloo