Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading Inifile to Stringlist problem spaces problem

Tags:

delphi

I am using the inifile to store values which I use to replace other values in a file for example A with B A=B which works fine however if I a space before the value B this is Ignored when reading in EG A= B is still read in as just 'B' rather than ' B', does anyone have any idea how I can work fix this, I am using Delphi 7 so I cannot use the StrictDelimiter option.

procedure ReadIntoVList(const aSection:string;AValueList:TValueListEditor);
var
  IniFile:TIniFile;
  SL: TStringList;
  i: Integer;
begin
   SL := TStringList.Create;
   IniFile := TIniFile.Create(ChangeFileExt(Application.Exename, '.ini'));
   try
     IniFile.ReadSectionValues(ASection, SL);
     AvalueList.Strings.AddStrings(SL);
   finally
     StampIniFile.Free;
     SL.Free;
   end;
end;

Thanks

Colin

like image 998
colin Avatar asked Sep 13 '10 17:09

colin


2 Answers

TIniFile.ReadSectionValues ultimately uses the Windows API function GetPrivateProfileString to read key values from the ini file. GetPrivateProfileString will remove any leading and trailing white space as well as any quotation marks surrounding the string.

This means that the line

[ key = value1 value2 value3 ]

will return the same value as the line

[ key=value1 value2 value3 ]

(square brackets added to show extra spaces).

In order to preserve any leading and trailing spaces, you will have to enclose your strings in either single or double quotation marks when writing them back into the ini.

As GetPrivateProfileString removes any surrounding quotation marks (single or double) you do not need to remove them when you read the values from the ini file.

To add the quotation marks you should NOT use a function AnsiQuotedStr function as Francois mentioned (edit unless you take special care to pick a quote char that is very very unlikely to be in the string in the first place). AnsiQuotedStr will add surrounding double quotation marks, but it will also double up any double quotation marks already in the string. While this is desired behaviour when you subsequently use AnsiDequoteStr, it is not when you use TIniFile to read the values as GetPrivateProfileString will remove the surrounding quoatation marks, but it will NOT de-double embedded ones.

So if you are going to read values from a file using TIniFile and want to preserve leading and trailing whitespace, you will have to add the surrounding quotation marks yourself and make sure that any embedded quotation marks are not doubled up (or you will have to de-double them yourself after reading them with TIniFile).

like image 168
Marjan Venema Avatar answered Nov 15 '22 04:11

Marjan Venema


You may want to enclose your strings in special quotes (not the regular single or double) to preserve the spaces (same idea as using double quotes with long filenames containing blanks) when writing to the INI file and remove the quotes when reading back.
You can do that with AnsiQuotedStr and AnsiDequotedStr from SysUtils. (don't know if they existed in D7 though)

Update: as pointed out by Marjan, you must not use the regular ' or " if you use a plain TIniFile, as they will be removed on both ends, while those in the middle will be left untouched.
This has the nasty side effect that if you write plainly what you just read, then you're not ending up with the same value (unless you always specifically add quotes at both ends before writing).

This behavior does not happen if you use a TMemInifile to load the IniFile in memory all at once to speed up further reads and writes. The regular quotes are not removed and you can use them.
Nevertheless, if you plan on modifying the IniFile in a text editor, and you expect regular quotes as part of the values, it's still useful to use special quotes to enclose the strings and making sure they are doubled in case some were already there.

Bottom line: AnsiQuotedStr and AnsiDequotedStr with a special QuoteChar would work symetrically for reading and writing, whether you use a TIniFile or a TMemIniFile all the same.

like image 26
Francesca Avatar answered Nov 15 '22 04:11

Francesca