A couple of years ago I shared a method for copying any file within a SAS program. It was a simple approach, copying the file byte-by-byte from one fileref (SAS file reference) to another.
- It's coded as a SAS macro, so it is simple to reuse -- similar to a function.
- It copies the file content in chunks rather than byte-by-byte, so it's more efficient.
- It provides good error checks and reports any errors and useful diagnostics to the SAS log.
- It's an excellent example of a well-documented SAS program!
Bruno tells me that "copying files" within a SAS program -- especially from nontraditional file systems such as Web sites -- is a common need among his SAS students. I asked Bruno for his permission to share his solution here, and he agreed.
To use the macro, you simply define two filerefs: _bcin (source) and _bcout (target), then call the %binaryFileCopy() macro. Here is an example use that copies a file from my Dropbox account:
filename _bcin TEMP; filename _bcout "C:\temp\streaming.sas7bdat"; proc http method="get" url="https://dl.dropbox.com/s/pgo6ryv8tfjodiv/streaming.sas7bdat" out=_bcin ; run; %binaryFileCopy() %put NOTE: _bcrc=&_bcrc; filename _bcin clear; filename _bcout clear;
The following is partial log output from the program:
NOTE: BINARYFILECOPY start 17SEP2013:20:50:33 NOTE: BINARYFILECOPY infile=_bcin C:\SASTempFiles\_TD5888\#LN00066 NOTE: BINARYFILECOPY outfile=_bcout C:\temp\streaming.sas7bdat NOTE: BINARYFILECOPY processed 525312 bytes NOTE: DATA statement used (Total process time): real time 0.20 seconds cpu time 0.07 seconds NOTE: BINARYFILECOPY end 17SEP2013:20:50:34 NOTE: BINARYFILECOPY processtime 00:00:00.344
You can download the program -- which should work with SAS 9.2 and later -- from here: binaryfilecopy.sas
Update: using FCOPY in SAS 9.4
Within hours of my posting here, Vince DelGobbo reminded me about the new FCOPY function SAS 9.4. With two filerefs assigned to binary-formatted files, you can use FCOPY to copy the content from one to the other. When I first tried it with my examples, I had problems because of the way FCOPY treats logical record lengths. However, Jason Secosky (the developer for FCOPY and tons of other SAS functions) told me that if I use RECFM=N on each FILENAME statement, the LRECL would not be a problem. And of course, he was correct.
Here's my example revisited:
filename _bcin TEMP recfm=n /* RECFM=N needed for a binary copy */; filename _bcout "C:\temp\streaming.sas7bdat" recfm=n; proc http method="get" url="https://dl.dropbox.com/s/pgo6ryv8tfjodiv/streaming.sas7bdat" out=_bcin ; run; data _null_; length msg $ 384; rc=fcopy('_bcin', '_bcout'); if rc=0 then put 'Copied _bcin to _bcout.'; else do; msg=sysmsg(); put rc= msg=; end; run; filename _bcin clear; filename _bcout clear;