使用 FreePascal 在 Lazarus 中将 AnsiString 转换为 UnicodeString

Convert AnsiString to UnicodeString in Lazarus with FreePascal

我在这里找到了类似的主题,但其中 none 已经解决了我的问题,所以我在新线程中提问。

几天前,我更改了保存我正在开发的应用程序首选项的格式,从 INI 更改为 JSON。

我为此使用了 jsonConf 单元。

我用来在文件中保存键值对的代码示例如下所示。

Procedure TMyClass.SaveSettings();
var
  c: TJSONConfig;
begin
  c:= TJSONConfig.Create(nil);
  try
    c.Filename:= m_settingsFilePath; 
    c.SetValue('/Systems/CustomName', m_customName);
  finally
    c.Free;
  end;
end;

在我的代码中,m_customName是一个AnsiString类型的变量。 TJSONConfig.SetValue 过程要求键和值都是 UnicodeString 类型。应用程序编译正常,但我收到这样的警告

Warning: Implicit strung type conversion from "AnsiString" to "UnicodeString". 

有些消息警告称可能会丢失数据。

当然我可以把所有的东西都改成UnicodeString类型,但这太冒险了。到目前为止,通过忽略这些警告我没有看到任何问题,但它们一直出现并且可能会在另一台 PC 上引起问题。

我该如何解决这个问题?

为了避免警告,请进行显式转换,因为这样您就可以告诉编译器您知道自己在做什么(我希望...)。在 c.SetValue 的情况下,预期类型是 Unicodestring (UTF16),m_customname 应该声明为 string 除非有充分的理由做不同的事情(见下文),否则你可能会触发不需要的内部转换。

Lazarus 中的 string 默认是 UTF8 编码的。所以UTF8到Unicode的转换可以使用函数UTF8Decode(),或者UTF8ToUTF16()(unit LazUtf8)。

var
  c: TJSONConfig;
  m_customName: String;
...
  c.SetValue('/Systems/CustomName', UTF8Decode(m_customName));

你在上面说键值对在一个文件中。然后转换取决于文件的编码。通常我在一个好的文本编辑器中打开文件并在某处找到编码 - 例如 NotePad++,在状态栏的右上角显示编码的名称。假设编码是代码页 1252 (Latin-1)。这些是反字符串,因此,您可以将从文件中读取的字符串声明为 ansistring。因为 UTF8 字符串在 Lazarus 中很常见,所以没有从 ansistring 到 Unicode 的直接转换,您必须先转换为 UTF8。在单元 lconvencoding 中,您会发现许多各种编码之间的转换例程。 Select CP1252toUTF8() 转到UTF8,然后应用UTF8Decode() 最终得到Unicode。

var
  c: TJSONConfig;
  m_customName: ansistring;
...
  c.SetValue('/Systems/CustomName', UTF8Decode(CP1252ToUTF8(m_customName)));

FreePascal 编译器 3.0 可以使用带有预定义编码的字符串自动处理其中的许多转换。但我认为显式转换非常清楚,可以看到发生了什么。而且 fpc3.0 仍然会发出您想避免的警告...