Преобразование текста без разделителей в пары имя / значение в Delphi
У меня есть текстовый файл, который поступает в мое приложение как много строк следующей формы:
и я хотел бы превратить эту "строку" в серию пар имя / значение в данном TStringList (в файле может быть несколько десятков этих <строк>, поэтому в конечном итоге я захочу перебрать файл, разбивая каждый по очереди в пары имя / значение).
У меня проблема в том, что данные явно не разграничены (технически, я полагаю, они разделены пробелом). Теперь, если бы не тот факт, что некоторые значения содержат начальные или конечные пробелы, я мог бы, вероятно, сделать несколько разумных предположений и написать код для разбивки строки на основе пробелов. Но поскольку сами значения могут содержать или не содержать пробелы, я не вижу очевидного способа сделать это. Delphi' TStringList.CommaText не помогает, и я попытался поиграться с Delimiter, но каждый раз меня ловят пробелы внутри значений.
У кого-нибудь есть умная техника Delphi для превращения приведенного выше примера во что-то похожее на это?;
сумма ="192,00" магазин = "10" TRANSACTION_DATE = "2009-10-22T12: 08: 49,640" comp_name = "бла" comp_ref = "C65551253E7A4589A54D7CCD468D8AFA" name = "Аккрингтон"
К сожалению, как это обычно бывает с подобными вещами, я не имею никакого контроля над форматом данных для начала - я не могу вернуться и "сделать" их запятыми, например, в источнике. Хотя, наверное, я мог бы написать какой-нибудь код, чтобы превратить его в запятую, - но я бы лучше нашел способ поработать с тем, что у меня есть.
Это будет в Delphi 2007, если это будет иметь какое-либо значение.
2 ответа
procedure RowToStrings(const row: string; list: TStrings);
var
i : integer;
iDelim : integer;
inQuotes: boolean;
begin
iDelim := 0;
inQuotes := false;
for i := 1 to Length(row) do begin
if (row[i] = ' ') and (not inQuotes) then begin
list.Add(Copy(row, iDelim+1, i-iDelim-1));
iDelim := i;
end
else if row[i] = '"' then
inQuotes := not inQuotes;
end;
list.Add(Copy(row, iDelim+1, Length(row)-iDelim));
end;
procedure TForm37.Test;
var
row: string;
begin
row := 'amount="192.00" store="10" transaction_date="2009-10-22T12:08:49.640" ' +
'comp_name="blah " ' +
'comp_ref="C65551253E7A4589A54D7CCD468D8AFA" ' +
'name="Accrington "';
RowToStrings(row, ListBox1.Items);
end;
Вы говорите, что это не "явно разграничено", но для меня это очень очевидно разграничено, потому что это очень очевидно XML. Так что используйте парсер XML. Вы могли бы начать с Delphi's TXmlDocument
, Вы можете передать каждую строку "строки" парсеру отдельно, но я подозреваю, что все эти строки заключены в какой-то другой тег угловой скобки. Передайте весь этот файл анализатору, и он может помочь вам получить список объектов, представляющих строки, а затем вы можете запросить значения их атрибутов по имени.
Если вы попытаетесь разобрать XML, не обращая внимания на нюансы синтаксического анализа XML, рано или поздно вы обожжетесь.