How do I store and load a list of key-value pairs in a string?

23,231

The Names and Values by default have to be separated by =, in the style of Windows INI files. There's no way AFAICT to change that separator. As @SirRufo indicates in the comment (and which I had never noticed), you can change that using the TStringList.NameValueSeparator property.

This will give you an idea of what Delphi thinks is in your TStringList, which is not what you think it is:

procedure TForm1.FormCreate(Sender: TObject);
var
  SL: TStringList;
  Temp: string;
  i: Integer;
begin
  SL := TStringList.Create;
  SL.Delimiter := '|';
  SL.QuoteChar := '"';
  SL.StrictDelimiter := True;
  SL.DelimitedText := 'O=0 | ! .!=!.!';
  Temp := 'Count: ' + IntToStr(SL.Count) + #13;
  for i := 0 to SL.Count - 1 do
    Temp := Temp + Format('Name: %s Value: %s'#13, 
              [SL.Names[i], SL.ValueFromIndex[i]]);
  ShowMessage(Temp);
end;

This produces this output:

Sample ShowMessage output from above code

TStringList Names/Values probably isn't going to do what you need. It's not clear what your actual goal is, but it appears that a simple text file with a simple list of text|replacement and plain parsing of that file would work, and you can easily use TStringList to read/write from that file, but I don't see any way to do the parsing easily except to do it yourself. You could use an array to store the pairs when you parse them:

type
  TReplacePair = record
    TextValue: string;
    ReplaceValue: string;
  end;

  TReplacePairs = array of TReplacePair;

function GetReplacementPairs: TReplacePairs;
var
  ConfigInfo: TStringList;
  i, Split: Integer;
begin
  ConfigInfo := TStringList.Create;
  try
    ConfigInfo.LoadFromFile('ReplacementPairs.txt');
    SetLength(Result, ConfigInfo.Count);
    for i := 0 to ConfigInfo.Count - 1 do
    begin
      Split := Pos('|`, ConfigInfo[i];
      Result[i].TextValue := Copy(ConfigInfo[i], 1, Split - 1);
      Result[i].ReplaceValue := Copy(ConfigInfo[i], Split + 1, MaxInt);
    end;
  finally
    ConfigInfo.Free;
  end;
end;

You can then populate whatever controls you need to edit/add/delete the replacement pairs, and just reverse the read operation to write them back out to save.

Share:
23,231
Admin
Author by

Admin

Updated on June 05, 2020

Comments

  • Admin
    Admin almost 4 years

    I have a list of strings and the values they are to be replaced with. I'm trying to combine them in a list like 'O'='0',' .'='.', ... so it's easy for me to edit it and add more pairs of replacements to make.

    Right now the best way I could think of it is:

    var
      ListaLimpeza : TStringList;
    begin
      ListaLimpeza := TStringList.Create;
    
      ListaLimpeza.Delimiter := '|';
      ListaLimpeza.QuoteChar := '"';
      ListaLimpeza.DelimitedText := 'O=0 | " .=."';
    
      ShowMessage('1o Valor = '+ListaLimpeza.Names[1]+' e 2o Valor = '+ListaLimpeza.ValueFromIndex[1]);
    

    This works, but it's not good for visuals, since I can't code the before string (for ex ' .') like that (which is very visual for the SPACE character), only like (" .) so that the = works to assign a name and value in the TStringList.

  • Admin
    Admin almost 11 years
    yes, I understand. I believe I'm gonna need to go to another approach, I'm thinking in using: '|O|==|0| , | .|==|.| , ...' in a string and then using code so to dismantle it so that the proper replacements are identified. Is there any easier solution which would give me a visual code like that?
  • Ken White
    Ken White almost 11 years
    I added a suggestion for a solution, but TStringLists built-in functionality isn't going to help. You could always create your own descendant that would do this for you, though.
  • Sir Rufo
    Sir Rufo almost 11 years
    The NameValueSeparator char can changed by using the TStrings.NameValueSeparator property docwiki.embarcadero.com/Libraries/XE2/en/…
  • Marjan Venema
    Marjan Venema almost 11 years
    @SirRufo: Thanks man, didn't know of the property and it is gonna make my life a lot easier :)
  • Ken White
    Ken White almost 11 years
    @SirRufo: I'd never noticed that property either (I apparently didn't need it). Thanks. I updated my answer (with proper credit, of course).