1

我在这里找到了类似的主题,但没有一个能解决我的问题,所以我在一个新线程中问它。

几天前,我将保存我正在开发的应用程序首选项的格式从 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 上引起问题。

我该如何解决?

4

1 回答 1

3

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

默认情况下,Lazarus 中的Astring是 UTF8 编码的。因此,您可以使用该函数UTF8Decode()将 UTF8 转换为 Unicode,或UTF8ToUTF16()(unit LazUtf8 )。

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

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

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

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

于 2016-09-27T21:33:18.967 回答