【问题标题】:How to add ' character to the key and values in TIniFile如何将 ' 字符添加到 TINiFile 中的键和值
【发布时间】:2021-04-21 03:33:05
【问题描述】:

我正在使用 Delphi XE3。我使用TIniFile 写入.ini 文件。问题之一是当我使用WriteString() 将字符串写入ini 文件时。虽然原始字符串包含',但TIniFile会在写入ini文件后将其删除。更糟糕的是,当字符串同时包含 '" 时。

见下文:

procedure TForm1.Button4Click(Sender: TObject);
var
  Str, Str1: string;
  IniFile: TIniFile;
begin
  IniFile := TIniFile.Create('E:\Temp\Test.ini');

  Str := '"This is a "test" value"';
  IniFile.WriteString('Test', 'Key', Str);
  Str1 := IniFile.ReadString('Test', 'Key', '');

  if Str <> Str1 then
    Application.MessageBox('Different value', 'Error');

  IniFile.Free;
end;

有没有办法确保TIniFile 会在值周围写'

更新

我尝试在我的ini文件中转义和取消转义引号“以及=,如下所示:

function EscapeQuotes(const S: String) : String;
begin
    Result := StringReplace(S, '\', '\\', [rfReplaceAll]);
    Result := StringReplace(Result, '"', '\"', [rfReplaceAll]);
    Result := StringReplace(Result, '=', '\=', [rfReplaceAll]);
end;

function UnEscapeQuotes(const S: String) : String;
var
    I : Integer;
begin
    Result := '';
    I := 1;
    while I <= Length(S) do begin
        if (S[I] <> '\') or (I = Length(S)) then
            Result := Result + S[I]
        else begin
            Inc(I);
            case S[I] of
            '"': Result := Result + '"';
            '=': Result := Result + '=';
            '\': Result := Result + '\';
            else Result := Result + '\' + S[I];
            end;
        end;
        Inc(I);
    end;
end;

但是对于以下行:

'这是一个 \= 测试'='我的 Tset'

ReadString 只会读取 'This is a \=' 作为键,而不是 'This is a \= Test'

【问题讨论】:

  • 你的代码没有使用'。你确定写作有问题吗?根据GetPrivateProfileString(),当值“用单引号或双引号括起来时,标记被丢弃” - 读取应该是问题,嗯?
  • 尝试改用TMemIniFile。它可以解决TIniFile 的各种缺点。
  • @RemyLebeau,抱歉,我尝试使用 TMemIniFile,但它无法解决我的问题。
  • Str := '"This is a "test" value"'; 是无效字符串,因为它是不正确的标点符号。它包含两个字符串("This is a "" value"),孤立词 test 出现在引号之外。引号的规则是,如果短语在两个双引号之间,嵌入的引号应该是单引号(例如,“这是一个'测试'值”),如果外引号是单引号,那么内引号应该是双倍(例如,'This is a "test" value')。

标签: delphi ini


【解决方案1】:

您不能在 INI 文件中写入任何内容。但是您可以转义任何不允许或被 Windows 以特殊方式处理的字符。

下面的简单代码实现了一个基本的转义机制(可以优化):

function EscapeQuotes(const S: String) : String;
begin
    Result := StringReplace(S, '\', '\\', [rfReplaceAll]);
    Result := StringReplace(Result, '"', '\"', [rfReplaceAll]);
end;

function UnEscapeQuotes(const S: String) : String;
var
    I : Integer;
begin
    Result := '';
    I := 1;
    while I <= Length(S) do begin
        if (S[I] <> '\') or (I = Length(S)) then
            Result := Result + S[I]
        else begin
            Inc(I);
            case S[I] of
            '"': Result := Result + '"';
            '\': Result := Result + '\';
            else Result := Result + '\' + S[I];
            end;
        end;
        Inc(I);
    end;
end;

这样使用:

procedure Form1.Button4Click(Sender: TObject);
var
  Str, Str1: string;
  IniFile: TIniFile;
begin

  IniFile := TIniFile.Create('E:\Temp\Test.ini');
  try

    Str := '"This is a "test" for key=value"';
    IniFile.WriteString('Test', 'Key', EscapeQuotes(Str));
    Str1 := UnEscapeQuotes(IniFile.ReadString('Test', 'Key', ''));

    if Str <> Str1 then
      Application.MessageBox('Different value', 'Error');

  finally
    IniFile.Free;
  end;

end;

当然,您也可以转义其他字符,例如控制字符,如 CR 和 LF。你有这个想法:-)

【讨论】:

  • 抱歉,您的代码不适用于 '=' equal。
  • @alancc 然后请更新您的问题以包含= 不起作用的示例。
  • @alancc 对不起,但它也适用于同样的罪恶。我用 Str := '"This is a "test" for key=value"'; 测试了代码你在哪里插入相等?通过用所有不起作用的情况更新您的问题来展示一个示例。
  • 非常感谢。最后我使用你的解决方案,有一个变体。我使用 \x3D 来转义等号,因此等号将不再出现在转义的字符串中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-04
  • 2020-09-20
  • 2011-04-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多