As the first step in the decommissioning of sasCommunity.org the site has been converted to read-only mode.


Here are some tips for How to share your SAS knowledge with your professional network.


Creating a ZIP File Using Native SAS Features

From sasCommunity
Revision as of 17:06, 19 September 2012 by JackHamilton (Talk | contribs)

Jump to: navigation, search

This Wiki entry came out of a presentation at WUSS 2012 in Long Beach, Creating a ZIP File using Native SAS® Features, by Jack Hamilton, Division of Research, Kaiser Permanente, Oakland, California.

What is a ZIP file?

  • A single file containing one or more internal files.
  • Files in a ZIP file are usually compressed, sometimes by as much as 99%.
  • Files in a ZIP file may be organized in a directory structure.

Why use a ZIP file?

  • To save space.
  • To package logically or physically connected files together.
  • To facilitate the distribution of groups of files.

What software uses ZIP files?

In addition to ZIP files with the name *.zip, the ZIP format is used for:

  • SAS Enterprise Guide projects (.prj)
  • Java program archive files (.jar)
  • Microsoft Office documents (.docx, .xlsx, .pptx)
  • Firefox extensions (.xpi)

… and more!

The Old Way

ZIP files have traditionally been created in one of two ways:

  • In a GUI, using a program such as WinZIP.
  • Using a command line, with a program such as Info-ZIP or WinZIP, or even the original PKZIP.

So what's the problem?

The old approaches have four major problems:

  • They are platform-dependent - you can't use one program that will run on Windows and Unix and z/OS.
  • Even if you know the platform, you can't count on a particular program being installed.
  • GUI's can't (usually) be automated.
  • Not all sites allow external programs to be called from SAS.

What's the solution?

  • In SAS 9.2 and later, you can use ODS to create a "package", which is a ZIP file.

The Steps

  • Create a package
  • Add files
  • Close the package and write the ZIP file

Use the ODS PACKAGE statement to tell SAS you want to create a package

 
ods package(packagename) 
    open nopf;

You might also call this "defining" a package.

Add each file to the ZIP in a separate statement

ods package(packagename) 
    add file='filename';

The file isn't added at this time; this just tells SAS what to add later. You might execute this statement hundreds of times.

Write the ZIP file

Finally, write (or publish) the ZIP file:

ods package(packagename)
    publish archive
    properties(archive_name= 
       'zipname.zip'            
    archive_path='path');

A working example

ods package(ProdOutput) open nopf;
ods package(ProdOutput) 
    add file='c:\temp\renal.xps';
ods package(ProdOutput) 
    publish archive        
       properties
      (archive_name=  
                  'ProdOutput.zip'                  
       archive_path='c:\temp');
ods package(ProdOutput) close;

The note in the log after the publish statement is:

NOTE: Writing zip package 
      c:\temp\ProdOutput.zip.

The Result

Here is the resulting ZIP file, as shown by the free compression tool 7ZIP:

Creating-a-ZIP-File-Using-Native-SAS-Features-7zipresult.png

This particular file did not compress very much

Adding internal structure

To create an internal directory structure in the ZIP file, use the PATH= option in the ADD statement:

ods package(ProdOutput) add 
    file='c:\temp\renal.xps'
    path='Diseases';

The structure in the ZIP file does not have to match the structure in the file system.

Cautions

  • It's not possible to add an empty internal directory.
  • You can't add files to an existing ZIP file.
  • The files you want to add have to exist when the PUBLISH statement executes.
  • There's no documented or supported way to read a ZIP file in SAS, even though the software obviously has the capability internally.

Automating ZIPping

These examples assume that you know the names of all the files you will want to add to the ZIP file.

If the file names vary, but you have the names in a SAS data set, you can write the ADD statements with CALL EXECUTE.

An example of automation

filename dirlist pipe 'dir /b y:\wuss2012\*.sas';
data _null_;
    infile dirlist pad lrecl=80;
    input @1 filename $80.;
    call execute
        (catx
            (' ',
            'ods package(vary)',
             'add file=',
             quote('y:\wuss2012\' || trim(filename)), 
             ';'
            )
        );
run;

For a different, platform-independent way to get file names, see my paper on reading directories.

Questions Asked at WUSS 2012

Q: Can you use wildcards instead of specifying each filename individually? A: It does not appear so.

Q: Will there be other ways to do this in the future? A: SAS 9.4 might have a filename engine, so you could code filename z zip 'my.file.name'; . This will also allow you to read ZIPped files.

Q: Is encryption supported? A: Not currently.

Q: Can a fileref be used instead of a physical filename? A: It appears so.


Original Paper Contact

Jack Hamilton via sascommunity.org


Sample Code

/* Simple code creating ZIP file */
ods package(ProdOutput) open nopf;
ods package(ProdOutput) add file='c:\temp\renal.xps';
ods package(ProdOutput) publish archive 
        properties(archive_name='ProdOutput.zip'
                   archive_path='c:\temp');
ods package(ProdOutput) close;
 
 
/* Writing same file to multiple ZIP locations. */
ods package(ProdOutput) open nopf;
ods package(ProdOutput) add 
    file='c:\temp\renal.xps'
    path='temp';
ods package(ProdOutput) add 
    file='c:\temp\renal.xps'
    path='temp2';
ods package(ProdOutput) publish archive 
        properties(archive_name='ProdOutput.zip'
                   archive_path='c:\temp');
ods package(ProdOutput) close;
 
 
/* Multiple files, dynamic, under Windows */
ods package(vary) open nopf;
 
filename dirlist pipe 'dir /b y:\wuss2012\*.sas';
data _null_;
    infile dirlist pad lrecl=80;
    input @1 filename $80.;
    call execute
        (catx
            (' ',
            'ods package(vary)',
             'add file=',
             quote('y:\wuss2012\' || trim(filename)), 
             ';'
            )
        );
run;
 
ods package(vary) publish archive 
    properties(archive_name='vary.zip'
               archive_path='c:\temp');
ods package(vary) close; 
 
 
/* Using fileref instead of physical filename */
ods package(ProdOutput2) open nopf;
filename renalxps 'c:\temp\renal.xps';
ods package(ProdOutput2) 
    add file=renalxps;
ods package(ProdOutput2)
    publish archive properties
    (archive_name='ProdOutput2.zip' archive_path='c:\temp');
filename renalxps clear;
ods package(ProdOutput2) close;
 
 
/* Converting to EBCDIC before ZIPping */
/* Needs work.                         */
options noxwait;
filename sometext 'c:\temp\some.txt' encoding=ebcdic037;
data _null_;
    file sometext;
    do i = 1 to 10;
        put i=;
    end;
run;
ods package(ToEBCDIC) open nopf;
ods package(ToEBCDIC) 
    add file=sometext;
ods package(ToEBCDIC)
    publish archive properties
    (archive_name='ToEBCDIC.zip' archive_path='c:\temp');
filename sometext clear;
ods package(ToEBCDIC) close;
x start c:\temp\toebcdic.zip;


Original Papers

PowerPoint presentation: File:WUSS-2012-Creating-a-ZIP-File-Using-Native-SAS-Features.pdf

Paper: File:WUSS-2012-Paper-Creating-a-ZIP-File-Using-Native-SAS-Features.pdf


Discussion

Please use the discussion tab to comment on or ask questions about this example.