2016-09-27 6 views
1

Здесь я нашел похожие темы, но ни один из них не смог решить мой вопрос, поэтому я прошу об этом в новом потоке.Преобразование AnsiString в UnicodeString в Lazarus с FreePascal

Пару дней назад я изменил формат, в котором сохраняются настройки приложения, которое я разрабатываю, от 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, но это слишком рискованно. Пока я не видел никаких проблем, игнорируя эти предупреждения, но они все время появляются, и это может вызвать проблемы на другом ПК.

Как исправить это?

+1

Почему бы вам просто не использовать 'string' везде? –

+0

Тогда он будет жаловаться «Предупреждение: Неявное преобразование типа строки из« ShortString »в« UnicodeString ». –

+0

Почему 'string' является псевдонимом' ShortString'? Я не понимаю, почему вы хотите использовать «ShortString» и «AnsiString». –

ответ

3

Чтобы избежать предупреждения, сделайте явное преобразование, потому что таким образом вы сообщаете компилятору, что знаете, что делаете (надеюсь ...). В случае c.SetValue ожидаемый тип является Unicodestring (UTF16), m_customname должен быть объявлен как string, если нет веских оснований для этого (см. Ниже), в противном случае вы можете инициировать нежелательные внутренние преобразования.

A string в Lazarus по UTF8-кодировке. Поэтому вы можете использовать функцию UTF8Decode() для преобразования из UTF8 в Unicode или UTF8ToUTF16() (unit LazUtf8).

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

Вы говорите выше, что пары ключ-значение находятся в файле. Тогда преобразование зависит от кодировки файла. Обычно я открываю файл в хорошем текстовом редакторе и где-то вижу кодировку - NotePad ++, например, отображает имя кодировки в правом углу панели состояния. Предположим, что кодировка кодирует код 1252 (латинский-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 все еще испускает предупреждения, которые вы хотите избежать ...

+0

Спасибо. То, что я хотел знать, было в этом ответе. Явное преобразование AnsiString в UnicodeString: UTF8Decode Явное преобразование UnicodeString в AnsiString: UTF8Encode Вид чувствую, что имена должны быть наоборот. Я не жалуюсь. –

+0

Я чувствую себя с вами - никогда не повезло с этими именами и предпочитаю функции UTF8ToUTF16 и UTF16ToUTF8. –