【问题标题】:Reading Inifile to Stringlist problem spaces problem读取 Inifile 到 Stringlist 问题空间问题
【发布时间】:2010-09-13 17:00:21
【问题描述】:

我正在使用 inifile 来存储用于替换文件中其他值的值,例如用 B A=B 替换 A 的值,但是如果我在值 B 之前有一个空格,则在读取 EG A= B 时会忽略此值仍然只是读入'B'而不是'B',有没有人知道我该如何解决这个问题,我使用的是Delphi 7所以我不能使用StrictDelimiter选项。

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;

谢谢

科林

【问题讨论】:

  • 本应记录在案的令人讨厌的 Delphi 功能。嘿!这听起来就像“错误”的定义(“错误是未记录的功能”):)

标签: delphi


【解决方案1】:

TIniFile.ReadSectionValues 最终使用 Windows API 函数 GetPrivateProfileString 从 ini 文件中读取键值。 GetPrivateProfileString 将删除任何前导和尾随空格以及字符串周围的任何引号。

这意味着该行

[ key = value1 value2 value3 ]

将返回与该行相同的值

[ key=value1 value2 value3 ]

(添加方括号以显示额外的空格)。

为了保留任何前导和尾随空格,在将字符串写回 ini 时,您必须用单引号或双引号将它们括起来。

由于 GetPrivateProfileString 会删除任何周围的引号(单引号或双引号),因此您在从 ini 文件中读取值时无需删除它们。

要添加引号,您不应使用 Francois 提到的函数 AnsiQuotedStr 函数 (edit 除非您特别注意选择不太可能出现在首先是字符串)。 AnsiQuotedStr 将添加周围的双引号,但它也会将字符串中已有的任何双引号加倍。虽然这是您随后使用 AnsiDequoteStr 时所期望的行为,但在您使用 TIniFile 读取值时却不是这样,因为 GetPrivateProfileString 会删除周围的引号,但不会消除嵌入的引号。

因此,如果您要使用 TIniFile 从文件中读取值并希望保留前导和尾随空格,则必须自己添加周围的引号并确保任何嵌入的引号都不会加倍(或者您使用 TIniFile 阅读它们后,必须自己对它们进行去倍处理)。

【讨论】:

  • AnsiQuotedStr 将添加您指定的 whatever QuoteChar。使用特殊引号(不是 ' 或 ")将毫无问题地工作。然后,您将有一个对称的读取和写入过程,而不是在没有引号的情况下使用引号写入,并且永远不能保证读取您在 IniFile 中手动输入的内容一个文本编辑器。
  • @Francois:啊,是的,这是个有趣的想法,尽管您必须非常小心地选择“引号”字符,使其不太可能出现在源字符串中。在我关于 AnsiQuotedStr 使用的评论中添加了一个限定符。
【解决方案2】:

您可能希望在写入 INI 文件时将字符串括在特殊引号中(不是常规的单引号或双引号)以保留空格(与使用包含空格的长文件名的双引号相同)并在读取时删除引号返回。
您可以使用来自SysUtilsAnsiQuotedStrAnsiDequotedStr 来做到这一点。 (不知道它们是否存在于 D7 中)

更新: 正如 Marjan 所指出的,你不能使用常规的 ' 或 " 如果你使用普通的 TIniFile,因为它们会在两端被删除,而中间的那些将保持不变。
这有一个讨厌的副作用,如果你清楚地写出你刚刚读到的东西,那么你最终不会得到相同的值(除非你总是在写之前专门在两端添加引号)。

如果您使用 TMemInifile 一次将 IniFile 全部加载到内存中以加快进一步的读取和写入,则不会发生此行为。 正则引号不会被删除,您可以使用它们。
不过,如果您计划在文本编辑器中修改 IniFile,并且希望将常规引号作为值的一部分,那么使用特殊引号将字符串括起来并确保它们加倍以防万一有些已经存在,仍然很有用。

底线: AnsiQuotedStrAnsiDequotedStr 带有特殊的 QuoteChar 将在读写时对称地工作,无论您使用 TIniFile 还是 TMemIniFile 都一样.

【讨论】:

  • 如果您使用 TIniFile,则在读取字符串时不需要删除引号。这是因为 TINiFile 内部使用 GetPrivateProfileString,这将删除单引号或双引号。 MSDN:If the string associated with lpKeyName is enclosed in single or double quotation marks, the marks are discarded when the GetPrivateProfileString function retrieves the string.
  • @Marjan。 AnsiQuotedStr 的优点是您可以选择要使用的 QuoteChar。不使用常规的单引号或双引号很简单。这就是我使用“特殊引号”的原因。我会让我的答案更清楚。
【解决方案3】:

也许您可以在保存 StringList 之前使用 StringReplace 将所有前导空格更改为您的数据永远不会包含的某个字符,例如 @ 符号?)然后在读取数据时执行相反的操作?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-02-19
    • 1970-01-01
    • 2016-05-11
    • 1970-01-01
    • 2010-11-06
    • 2021-01-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多