Skip to content

Browsing archive files with libstreams

Saturday, 21 February 2009  |  oever

ArchiveReader is a class in libstreams that allows you to open files embedded in zip, deb, rpm, jar, openoffice, and email files. It is used in the kio slave jstreams:/. This class works like this:

    /* create an ArchiveReader that reads files on the local filesystem */
    ArchiveReader reader;
    FileStreamOpener streamopener;
    reader.addStreamOpener(&streamopener);

    /* read an embedded file */
    InputStream* stream = reader.openStream("/home/james/archive.zip/package.deb/README.txt");
    doSomethingUseful(stream);
    reader.closeStream(stream);

    /* list embedded files */
    ArchiveReader::DirLister lister = reader.dirEntries("/home/james/archive.zip/package.deb");
    EntryInfo entryinfo;
    while (lister.nextEntry(entryinfo)) {
        doSomethingUseful(entryinfo.filename);
    }

For the next Strigi release DirLister has been much improved. The old implementation contained a simple vector with EntryInfo objects. This implementation would read an entire archive before returning the first entry. Interactive applications like Dolphin would have to wait a long time before they could show something.

The new application has a pointer to a ListingInProgress object which reads entries on demand. So now interactive applications can update their view as more results come in.

When an entire archive is read, the entries in it are cached inside the ArchiveReader object. If the contents of an archive is listed twice there is no need for DirLister to read the archive again (unless it has changed).

Multiple concurrent DirListers can read from the same archive at the same time and they will share the (internal) ListingInProgress object.

The emphasis in the new ArchiveReader is on speed and ease of use. This means that implementing it was not easy. Nevertheless the implementation is quite clean and readable. ArchiveReader can be a convenient base for a KIO, FUSE or GVFS implementation. By implementing a different StreamOpener and supplying it to ArchiveReader you can access remote sources.