Импорт плоского файла с разделителями строк и столбцов

Я импортирую плоский файл.txt с разделителями строк и столбцов. Проблема заключается в том, что разделитель строк используется для уменьшения размера файла, поэтому часто остальные столбцы пропускаются. Другая проблема заключается в том, что длина самого длинного символа неизвестна, и поэтому, если эта строка символов усекается, мы теряем разделитель, и вся структура разваливается.

Явный пример проблем, с которыми я сталкиваюсь, включает

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;

Любой опыт и понимание очень ценится.

1 ответ

Если у вас есть одна запись на строку, то просто используйте missover или же 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, так и должно быть). Тогда он не будет пытаться выписать полную переменную длину. Если это не поможет, вам, возможно, придется пересмотреть структуру набора данных, чтобы избежать этой проблемы - вам нужно будет задать отдельный вопрос с гораздо большим количеством деталей, чтобы найти там лучшее решение.

Другие вопросы по тегам