Correct Syntax for Filename Statement using a dataset variable

Viewed 355

I'm a SAS newbie and I don't seem to be able to work out the correct syntax for this. I have a dataset (fileList) with one field (projFile) which holds a filename. I wish to open the file and read the contents into a second field that will be created. The file is zipped (it's a SAS-EG project file) and so I'm told that I should use Filename statement with the zip option to read the file. However, no matter how I reference projFile it doesn't like it.

data fileList;
set fileList;
    filename inzip zip "&projFile" member="project.xml";
    infile inzip;
    input fileContent $char2000.;
    output;
run;

I may also have the input statement wrong, but until I can get past this issue, I don't know. Thanks.

2 Answers

If you are always reading the same file (member) from the ZIP file you can use the FILEVAR= option on the infile statement to switch which ZIP file you are reading that member from.

So if I have three ZIP files that each has a file named example.txt in it and a dataset like this with the list of filenames.

data fnames ;
  input filename $80.;
cards;
c:\downloads\file1.zip
c:\downloads\file2.zip
c:\downloads\file3.zip
;

Then I can use that dataset to drive the creation of a new dataset that has the information from those files.

data test;
  set fnames ;
  fname=filename;
  infile in zip filevar=fname member='example.txt' end=eof truncover;
  do while (not eof);
    input line $100. ;
    output;
  end;
run;

If the driving dataset has the list of members in the ZIP file to read then you can use the MEMVAR= option on the INFILE statement also.

data members ;
  infile cards dsd dlm='|' truncover ;
  input filename :$80. memname :$80.;
cards;
c:\downloads\file1.zip|example.txt
c:\downloads\file2.zip|example.txt
c:\downloads\file3.zip|example.txt
;

data test;
  set members ;
  filevar=filename;
  memvar=memname;
  infile in zip filevar=filevar memvar=memvar end=eof truncover;
  do while (not eof);
    input line $100. ;
    output;
  end;
run;

There's a few issues here.

First - you probably shouldn't use data filelist; set filelist; if you're doing something like this. Make a new dataset.

Second - filename is not executable. It is declarative. You can place it inside the data step, but you shouldn't, and for precisely this reason: it makes you think it's doing something inside the data step. It's not. It's doing something, period, and then the data step happens, later (even when placed here).

Third - you aren't using infile properly, but that's really a consequence of Second. You need the filevar option on infile to allow it to do something different here.

Fourth - you probably don't really want to just read arbitrarily from the project.xml. Really this whole thing is probably not what you want to do... I've done what you're doing, and it's doable, but not this way. But that's probably a bigger question.

If this were to work, what you'd do is this:

filename a zip "c:\doesntmatter.egp" member="project.xml";

data files;
  length fname $255;
  infile datalines truncover;
  input @1 fname $255.;
datalines;
c:\myfile.egp
c:\myfile2.egp
c:\myfile3.egp
;;;;
run;

data egp;
  set files;
  infile a filevar=fname pad truncover;
  input @1 first_line $512. @;
  put first_line;
run;

The filename statement doesn't really do anything, but I show you where it would go. You see the filevar on the infile statement - that points to the fname variable on files. Then it reads in from there.

My general suggestion is that you should probably use the xml libname engine here; figure out what you want to do on a per-xml basis, write that out as a macro, then call the macro for each line in the file name dataset (using call execute probably, or if you must, dosubl). You don't have to use the xml libname engine, but it'll simplify things most likely.

If you're only using one file, then you can specify it directly in the filename statement I showed above, and just use infile with that filename (infile a; here, but please call it something more sensible than a). But again, it's silly to read it in this way - use the libname engine, as it'll parse out the xml for you.


Edits, to remove incorrect information confirmed by Tom's answer. Even though it does work, I don't recommend using infile here - read it with the libname engine, it'll save you loads of time.

Related