I need to find the file length of a binary file to use in calculating the number of records in the file. I found a way to get the file length but it takes an extra Data step and finding the file length takes longer than reading the file. (Most likely do to my poor codeing.)
The data step below works, but like I said it's slow.
data _null_;
infile "&dspath.&dsname." recfm=n;
input a $char1.;
i+1;
call symput('file_len',trim(left(i)));
run;
Thanks Vince
Walking the entire file seems like a waist of resources. Why not use the finfo function?
Eg.
data fileatt; length name $ 20 value $ 40; drop fid j infonum; filename myfile "&dspath.&dsname."; fid=fopen("myfile"); infonum=foptnum(fid); do j=1 to infonum; name=foptname(fid, j); value=finfo(fid, name); put 'File attribute' name 'has a value of ' value; output; end; run;
Have a look at the doc to get to filesize directly plus OS specifics.
Hope this helps,
- Jan.
EDIT: In case of UTF-8 or other multibyte encoding the size in characters does not always equal the size in bytes.
Here's a variation on your DATA step that should speed it up somewhat:
data _null_;
infile "&dspath.&dsname." recfm=n end=done;
input a $char1.;
if done then call symputx ('file_len', _n_);
run;
I think I tried this. "END" can not be used for unbuffered reads and when you add "recfm=n" for a binary file it's unbuffered. So I think "done" never becomes TRUE.
Vince
Where there's a will there's a way. Let's try it this way:
data _null_;
infile "&dspath.&dsname." recfm=n eof=done;
input a $char1.;
return;
done: call symputx ('file_len', _n_);
stop;
run;
But make sure that _N_ is the right value to use. It might conceivably be _n_ - 1, depending on when the EOF logic kicks in. If that's a problem, you can always go back to your original idea:
data _null_;
infile "&dspath.&dsname." recfm=n eof=done;
input a $char1.;
i + 1;
return;
done: call symputx ('file_len', i);
stop;
run;
Walking the entire file seems like a waist of resources. Why not use the finfo function?
Eg.
data fileatt; length name $ 20 value $ 40; drop fid j infonum; filename myfile "&dspath.&dsname."; fid=fopen("myfile"); infonum=foptnum(fid); do j=1 to infonum; name=foptname(fid, j); value=finfo(fid, name); put 'File attribute' name 'has a value of ' value; output; end; run;
Have a look at the doc to get to filesize directly plus OS specifics.
Hope this helps,
- Jan.
EDIT: In case of UTF-8 or other multibyte encoding the size in characters does not always equal the size in bytes.
Excelent, this is just waht I was after. My code is now:
data _null_;
filename myfile "&dspath.&dsname.";
fid=fopen("myfile");
call symput('file_len',finfo(fid, 'File Size (bytes)'));
run;
%put &file_len;
It runs instantly.
Thanks,
Vince
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.