BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
VinceH
Fluorite | Level 6

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

1 ACCEPTED SOLUTION

Accepted Solutions
jklaverstijn
Rhodochrosite | Level 12

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.

View solution in original post

5 REPLIES 5
Astounding
PROC Star

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;

VinceH
Fluorite | Level 6

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 

Astounding
PROC Star

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;

jklaverstijn
Rhodochrosite | Level 12

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.

VinceH
Fluorite | Level 6

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

Ready to join fellow brilliant minds for the SAS Hackathon?

Build your skills. Make connections. Enjoy creative freedom. Maybe change the world. Registration is now open through August 30th. Visit the SAS Hackathon homepage.

Register today!
How to Concatenate Values

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 5 replies
  • 1299 views
  • 4 likes
  • 3 in conversation