2016-09-27 73 views
1

我在这里发现了类似的主题,但是他们都没有解决我的问题,所以我在新线程中提问。使用FreePascal将AnsiString转换为Lazarus中的UnicodeString

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

我该如何解决这个问题?

+1

为什么你不使用'string'到处? –

+0

然后它会抱怨'警告:隐式字符串类型从“ShortString”转换为“UnicodeString”'。 –

+0

为什么'string'是ShortString的别名?我不明白你为什么要使用'ShortString'和'AnsiString'。 –

回答

3

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

在默认情况下,Lazarus的A string采用UTF8编码。因此,您可以使用函数UTF8Decode()进行从UTF8到Unicode的转换,或使用UTF8ToUTF16()(单元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你可以在各种编码之间找到许多转换例程。选择CP1252到UTF8()转到UTF8,然后应用UTF8Decode()最终获得Unicode。

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

FreePascal编译器3.0可以使用具有预定义编码的字符串自动处理这些转换中的很多。但我认为明确的转换非常明确,看看发生了什么。而fpc3.0仍然会发出你想要避免的警告...

+0

谢谢。我想知道的是在这个答案。 明确地将AnsiString转换为UnicodeString:UTF8Decode 将UnicodeString明确转换为AnsiString:UTF8Encode 有种感觉名称应该是其他方式。我不抱怨。 –

+0

我感觉和你在一起 - 从来没有这些名字的幸运,喜欢UTF8ToUTF16和UTF16ToUTF8功能。 –

相关问题