Delphi: StringList Delimiter всегда является пробелом, даже если установлен Delimiter

У меня проблемы с разделителем в классе TStringList. Взглянуть:

var
  s: string;
  sl: TStringList;

begin
  sl := TStringList.Create;
  s := 'Users^foo bar^bar foo^foobar^barfoo';
  sl.Delimiter := '^';
  sl.DelimitedText := s;
  ShowMessage(sl[1]);
end;

sl[1] ДОЛЖЕН вернуться 'foo bar'

sl[1] Возвращается 'foo'

Кажется, что разделитель сейчас '^' А ТАКЖЕ ' '

Есть идеи?

6 ответов

Решение

Вы должны установить s1.StrictDelimiter := True для пробелов, которые не считаются разделителями, больше информации здесь.

Поскольку вы работаете в версии, которая не поддерживает вышеизложенное (как выяснилось после отправки ответа), у вас есть два варианта:

  1. Найдите символ, который, как вы знаете, не будет использоваться в исходном тексте (например, подчеркивание), преобразуйте все пробелы в этот символ перед разделением и выполните обратное преобразование после разделения. Это предложение robsoft.
  2. Если в тексте нет кавычек и пробелов, вы можете использовать хитрость Alex и обернуть текст между разделителями в инвертированную команду, чтобы 'hello hello^bye bye' превращается в '"hello hello"^"bye bye"', Если вы выбрали этот путь, и он работает для вас, примите ответ Александра, а не мой, он также предоставляет код для его реализации.

Оба обходных пути не используют StrictDelimiter есть ограничения: первый требует некоторого неиспользованного символа, а второй не требует кавычек и пробелов в исходном тексте.

Может быть, пришло время перейти на более новую версию Delphi:)

sl.DelimitedText := '"' + StringReplace(S, sl.Delimiter, '"' + sl.Delimiter + '"', [rfReplaceAll]) + '"';

У Райана есть отличное решение этой проблемы с помощью функции ExtractStrings() в Delphi. Увидеть:

Парсинг строки с использованием разделителя для TStringList, кажется, также анализирует пробелы (Delphi)

Так что в вашем случае замените вызовы sl.Delimiter и sl.DelimitedText следующей строкой:ExtractStrings (['^'], [], PChar (S), sl);

Работа в Delphi 7 "как перчатки" для меня. Это моя функция после применения трюка Александра:

procedure Split (const Delimiter: Char; Input: string; const Strings: TStrings) ;
begin
   Assert(Assigned(Strings)) ;
   Strings.Clear;
   Strings.Delimiter := Delimiter;
   Strings.DelimitedText :=  '"' + StringReplace(Input, Delimiter, '"' + Delimiter + '"', [rfReplaceAll]) + '"' ;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Edit1.Text := 'Users^foo bar^bar foo^foobar^barfoo';
  Split('^',Edit1.Text,Memo1.Lines);
end;

Большое спасибо!

sl.Text := StringReplace(S, sl.Delimiter, sLineBreak, [rfReplaceAll]);
      var
  MyString: String;
  Splitted: TArray<String>;

begin
  MyString := String.Join(',', ['String1', 'String2', 'String3']);
  Splitted := MyString.Split([','], 2);
end.

параметры:

Count : Максимальное количество расщеплений для возврата; по умолчанию MaxInt, если не указано иное.

QuoteStart/QuoteEnd : начальный и конечный символы заключенной в кавычки части строки, где разделитель игнорируется.

Параметры: определяет, включены ли какие-либо пустые совпадения или пустые совпадения в конце.

Больше информации

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