Data Operations

Archives Are Folders

A Path Can Go Through an Archive

Explorer has always shown a zip as a folder you can open. GPALFile does the same. Put the archive in the path where a folder would go and name what you want inside it, with or without a wildcard.

The files are taken out when WithFileName runs, the same moment a wildcard is expanded or a url is fetched, so everything that takes a GPALFile gets plain files on disk. None of it knows an archive was involved.

The archive is recognized by its contents, so it does not matter what it is called. An .xpi, a .jar, an .xlsx and a download saved with no extension all open, and a .tar.gz opens as the tar inside it.

// download, unpack, convert

browser

.WithSelector(exportLink)

.LeftClickAndDownload("C:\work\export.zip");


GPALFile orders = (GPALFile)GPAL.File

.WithFileName("C:\work\export.zip\orders.csv");


GPAL.Converter

.WithInput(orders)

.WithOutputType(DataFormat.JSON)

.SaveTo("C:\work\orders.json");

NOTE

What comes out of an archive lands in the GPAL temp directory, in a folder named after the archive with .contents on the end and a short code that keeps two archives of the same name apart. Only the files the path asked for are written. Like everything in the temp directory they are safe to delete, so copy out anything worth keeping.

Saving Is SaveTo

SaveTo makes an archive, and the destination's extension decides what kind, the same way the converter's SaveTo decides between json and csv. Names follow copy's rule. A name is one target, so reports.zip holds everything. A wildcard keeps each file's own name, so *.gz makes a.csv.gz and b.csv.gz. Leave the folder off and the archive goes beside the source.

A folder goes in whole, subfolders and all, with its contents at the top of the archive. That is what an extension package needs, with manifest.json at the root, and what a backup of a project folder wants. Saving a folder into itself is fine: the archive being written, and the ones earlier runs numbered from it, are left out.

// a project folder, packed whole

((GPALFile)GPAL.File

.WithFileName("C:\source\extension\"))

.SaveTo("C:\out\extension.xpi");


// the logs, compressed in place under their own names

((GPALFile)GPAL.File

.WithFileName("C:\logs\*.log"))

.SaveTo("*.gz");


// one zip of the reports, then the originals removed

((GPALFile)GPAL.File

.WithFileName("C:\reports\*.csv"))

.SaveTo("C:\out\reports.zip")

.Delete();

NOTE

WithOverwriteFile(true) replaces an archive already there. Without it the new archive takes the next free name, reports_0001.zip, the way .Next and CopyTo do, and every archive written is listed in ReturnFilenames. A compressed file keeps its inner extension when it is numbered, so the next reports.csv.gz is reports_0001.csv.gz and still unpacks to a .csv.

From the Web, and Which Formats

A url goes through an archive the same way a path does, as long as a wildcard follows it: https://example.com/export.zip/*.csv fetches the zip, then opens it. Without a wildcard the url is fetched as it stands, because plenty of real download links have .zip/ in the middle of them.

zip, 7z, rar and tar open, and so does a tar inside a gz, bz2 or xz. A gz, bz2 or xz holding a single file opens as a folder of one, named without the extension. SaveTo writes zip, gz, tar and tar.gz; 7z and rar open but are not written.

The zipExtensions and gzExtensions lists in GPAL.yaml say which other names SaveTo writes as a zip or a gz. They start with xpi, jar, vsix and nupkg for zip, and gzip and svgz for gz.

// fetched, then opened: every .log at the top of the tar

GPALFile logs = (GPALFile)GPAL.File

.WithFileName("https://example.com/builds/logs.tar.gz/*.log");


foreach (string log in logs.Filenames)

{

// an ordinary file on disk

}

WARNING

A gz is a single file compressed, not a folder. Several files saved to one named .gz are numbered reports.csv.gz, reports_0001.csv.gz and on, and a folder cannot be saved to a .gz at all. For more than one file, use .zip or .tar.gz.

💬 Ask GPAL