如何在SAS文件I/O数据步中直接标记文件的最后一行?
在SAS文件I/O读取时直接标记文件最后一行
要在读取文件的同一个数据步中生成最后一行标记(无需额外数据步),可以通过两种SAS文件I/O函数的组合实现,以下是具体方案:
方法1:通过总行数对比标记
利用fcount()函数获取文件的总记录数,逐行计数后对比判断是否为最后一行,代码直观易读:
data want; set have; length content $1024. flag 3; filref=filename('_dummy_',path); filrc=fopen('_dummy_'); if filrc then do; /* 移动文件指针到开头,获取总记录数 */ rc = fseek(filrc, 0, 0); total_lines = fcount(filrc); line_num = 0; do while(fread(filrc)=0); line_num + 1; rc = fget(filrc,content,1024); /* 当当前行号等于总行数时标记为最后一行 */ flag = (line_num = total_lines); output; end; filrc=fclose(filrc); end; run;
注意事项
fcount()会从当前指针位置统计到文件尾的记录数,因此需要先用fseek()将指针移到文件开头,确保统计的是总行数。- 若文件极大,
fcount()需要遍历整个文件统计行数,会带来一定性能开销。
方法2:预读下一行判断
通过预读下一行的方式,直接判断当前行是否为最后一行,无需提前统计总行数,适合处理大文件:
data want; set have; length content $1024. flag 3; filref=filename('_dummy_',path); filrc=fopen('_dummy_'); if filrc then do; /* 读取第一行 */ read_rc = fread(filrc); do while(read_rc=0); rc = fget(filrc,content,1024); /* 预读下一行,判断是否存在 */ next_read_rc = fread(filrc); /* 下一行读取失败则当前行是最后一行 */ flag = (next_read_rc ne 0); output; /* 若下一行存在,将指针回退一行,确保下一次循环能读取该行 */ if next_read_rc=0 then do; rc = fseek(filrc, -1, 1); read_rc = 0; end; else do; read_rc = next_read_rc; end; end; filrc=fclose(filrc); end; run;
原理说明
- 每次读取当前行后,尝试读取下一行:如果
fread()返回非0值,说明当前行是最后一行; - 若下一行存在,通过
fseek()将文件指针回退一行,保证下一次循环能正常读取该行。
两种方法生成的flag变量,结果均与后续通过by path notsorted生成的last.path完全一致,且无需额外数据步处理庞大的want数据集。
内容的提问来源于stack exchange,提问作者whymath
相关产品推荐
相关产品推荐

