3

我正在导入一个带有行和列分隔符的平面 .txt 文件。问题是行分隔符用于减小文件大小,因此通常会跳过其余列。另一个问题是最长字符的长度是未知的,因此,如果这个 char 字符串被截断,那么我们会丢失分隔符,整个结构就会分崩离析。

我面临的问题的一个明确示例包括

.txt 文件

Var1'~'Var2'~'Var3'~'Var4'~'Var5'~'Var6'#@#@'
1'~''#@#@'
This is going to be a really long string as an example of a situation where the long string is very large and so the truncated string does not indicate a delimiter and we lose data '#@#@'
1'~' 2'~' 3'~' 4'~' 5'~' 6'#@#@'
1'~' 2'~' 3'~''#@#@'

由于多种原因,我在尝试导入此数据时遇到了很多问题:

  1. 为字符变量设置非常大的长度会使导入过程非常耗时,而且我们不知道最长字符 var 的长度,因此每次迭代都需要更多时间

  2. 当结构意味着下一行可以在所有列都被填充之前发出信号时,我还没有找到一种方法来处理列和行分隔符,即不能只为行分隔符创建一个额外的列并删除它。

我尝试过的SAS代码:

data want;
infile "file-location" dlmstr = "#@#@" dsd recfm = F lrecl=10000000000;
informat var $200.
input var $ @@;
run;

非常感谢任何经验和见解。

4

1 回答 1

1

如果每行有一条记录,则只需在 infile 上使用missoveror选项;truncover这将告诉 SAS 在达到 EOL 后停止读取。您只需要处理奇怪的结束分隔符,因为如果您尝试将其读入数字会导致错误;您可以尝试在预处理中首先删除字符串。

data want;
  infile "yourfile-location" dlmstr="'~'" dsd lrecl=32767 truncover;
  input @;
  _infile_ = tranwrd(_infile_,"'#@#@'"," ");
  input var1 var2 var3 var4 var5 var6;
run;

如果由于某种原因上述方法不起作用,您在那里编写它的方式也可以工作;基本上使用两个不同的分隔符选项在字符串中读取两次,一次使用“'#@#@'”dlmstr,然后使用“'~'”dlmstr。或者与其读两次,不如用第一次读一次,然后用第二次解析。

data want;
  infile "yourfile-location" dlmstr="'#@#@'" dsd lrecl=32767;
  input @;
  array var[6] var1-var6;
  do _i = 1 to countc(_infile_,"~")+1;
    var[_i] = scan(_infile_,_i,"~");
  end;
run;

以上内容并不完美,因为它不处理分隔符周围的那些引号,但您可以根据细节弄清楚 - 引号是否可以安全地完全压缩预输入,或者您是否需要这样做SUBSTR 的一些花哨的步法?

就字符串可变长度而言,最有可能需要时间的是写出文件。用于options compress=char;打开数据集压缩,假设您对这些文件的最终用途与此兼容(如果您只是在它们上运行 SAS 代码,则应该如此)。然后它不会尝试写出完整的可变长度。如果失败了,您可能需要重新考虑您的数据集结构以避免出现此问题 - 您需要提出一个包含更多详细信息的单独问题,以便在那里找到最佳解决方案。

于 2018-10-16T15:09:32.450 回答