Skip to content

System.ArgumentException: 'Stream should be readable and seekable' #1294

@danies8

Description

@danies8

Hi,

My final aim is to properly support : 7Z, BZ2, GZ, RAR, TAR, TGZ, XZ, ZIP/

These 2 problems I encontered:
1.When I test this file kmz.xz un xip before testing,
I got "System.ArgumentException: 'Stream should be readable and seekable'".
2.BZip2Stream not complied.

Can you please help? Any good source ?
Thanks in advance,

kml.zip

`   public static IEnumerable<string>? TryListArchiveEntries(string archivePath)
   {
       if (string.IsNullOrWhiteSpace(archivePath))
       {
           Log.Warn("TryListArchiveEntries: archivePath is null or empty.");
           return null;
       }
       if (!File.Exists(archivePath))
       {
           Log.Warn($"TryListArchiveEntries: archive file not found: '{archivePath}'.");
           return null;
       }

       var ext = Path.GetExtension(archivePath).ToLowerInvariant();

       try
       {
           switch (ext)
           {
               // Real archives SharpCompress can open directly
               case ".zip":
               case ".rar":
               case ".7z":
               case ".tar":
                   return ListEntriesFromArchive(() => ArchiveFactory.OpenArchive(archivePath));

               // GZip single stream (.gz, .tgz -> .tar.gz)
               case ".gz":
               case ".tgz":
                   return ListEntriesFromCompressedTar(archivePath, s => new GZipStream(s, CompressionMode.Decompress));

               // BZip2 single stream
               case ".bz2":
                   return ListEntriesFromCompressedTar(archivePath, s => new BZip2Stream(s, CompressionMode.Decompress, false));

               // XZ single stream
               case ".xz":
                   return ListEntriesFromCompressedTar(archivePath, s => new XZStream(s));

               default:
                   Log.Warn($"TryListArchiveEntries: unsupported archive extension '{ext}'.");
                   return null;
           }
       }
       catch (Exception ex)
       {
           Log.Debug($"TryListArchiveEntries: SharpCompress failed to open '{archivePath}': {ex.Message}. Attempting ZipArchive fallback where applicable.");

           // Fallback only makes sense for .zip
           if (ext == ".zip")
           {
               try
               {
                   using var stream = File.OpenRead(archivePath);
                   using var za = new ZipArchive(stream, ZipArchiveMode.Read, leaveOpen: false);
                   return za.Entries.Select(e => e.FullName).ToList();
               }
               catch (Exception zipEx)
               {
                   Log.Warn($"TryListArchiveEntries: failed to read archive '{archivePath}' with SharpCompress and ZipArchive: {zipEx.Message}");
                   return null;
               }
           }

           Log.Warn($"TryListArchiveEntries: failed to read archive '{archivePath}': {ex.Message}");
           return null;
       }
   }

   private static IEnumerable<string> ListEntriesFromArchive(Func<IArchive> openArchive)
   {
       using var archive = openArchive();
       var list = new List<string>();

       foreach (var entry in archive.Entries)
       {
           try
           {
               if (entry == null || entry.IsDirectory)
                   continue;

               var name = entry.Key;
               if (!string.IsNullOrEmpty(name))
                   list.Add(name);
           }
           catch (Exception inner)
           {
               Log.Debug($"TryListArchiveEntries: skipped entry due to error: {inner.Message}");
           }
       }

       return list;
   }

   // For formats like .gz, .bz2, .xz that usually contain a TAR stream
   private static IEnumerable<string>? ListEntriesFromCompressedTar(
       string archivePath,
       Func<Stream, Stream> createDecompressStream)
   {
       using var fileStream = File.OpenRead(archivePath);
       using var decompressed = createDecompressStream(fileStream);

       // SharpCompress can open TAR from a stream
       using var archive = ArchiveFactory.OpenArchive(decompressed);

       var list = new List<string>();
       foreach (var entry in archive.Entries)
       {
           try
           {
               if (entry == null || entry.IsDirectory)
                   continue;

               var name = entry.Key;
               if (!string.IsNullOrEmpty(name))
                   list.Add(name);
           }
           catch (Exception inner)
           {
               Log.Debug($"TryListArchiveEntries: skipped entry in compressed TAR due to error: {inner.Message}");
           }
       }

       return list;
   }
   /*

`

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions