Как читать UI файл с кодировкой UTF8?
У меня есть файл INI в формате UTF-8.
Я использую Delphi 2010 для чтения INI файла и заполнения TStringGrid значениями в INI файле.
var
ctr : Integer;
AppIni : TIniFile;
begin
AppIni := TIniFile.Create(ExtractFilePath(Application.ExeName) + 'test.ini');
for ctr := 1 to StringGrid1.RowCount do begin
StringGrid1.Cells[0,ctr] := AppIni.ReadString('Column1','Row'+IntToStr(ctr),'');
StringGrid1.Cells[1,ctr] := AppIni.ReadString('Column2','Row'+IntToStr(ctr),'');
end;
AppIni.Free;
Проблема заключается в том, что символы Unicode появляются в TStringGrid, отображая 2 символа, а не 1 символ юникода.
Как это разрешить?
Ответы
Ответ 1
Класс TIniFile
является оболочкой Windows API для файлов INI. Это поддерживает Unicode INI файлы, но только если эти файлы закодированы как UTF-16. Майкл Каплан имеет более подробную информацию: Unicode INI функция; Unicode INI файл?
Итак, вам не повезло с TIniFile
. Вместо этого вы можете использовать TMemIniFile
, который позволяет указать кодировку в своем конструкторе. Класс TMemIniFile
является встроенной поддержкой файлов INI в Delphi. Между двумя классами существуют разные плюсы и минусы. В вашей ситуации только TMemIniFile
может удовлетворить ваши потребности, поэтому он выглядит как его профи, перевешивает его недостатки.
Ответ 2
Uses IniFiles;
const
SZ_APP_NAME = 'demo_test';
Procedure TForm1.GetSettings;
var
_MemIniU: TMemIniFile;
_SettingsPath: string;
begin
try
_SettingsPath := GetHomePath + PathDelim + SZ_APP_NAME + PathDelim;
if ForceDirectories(_SettingsPath) then
begin
_MemIniU := TMemIniFile.Create(ChangeFileExt(_SettingsPath,
'Settings.ini'), TEncoding.UTF8);
try
if _MemIniU.ReadInteger(SZ_APP_NAME, 'WindowLeft', -1) = -1 then
Form1.Position := poScreenCenter
else
begin
Form1.Left := _MemIniU.ReadInteger(SZ_APP_NAME, 'WindowLeft', 10);
Form1.Top := _MemIniU.ReadInteger(SZ_APP_NAME, 'WindowTop', 10);
Form1.Width := _MemIniU.ReadInteger(SZ_APP_NAME, 'WindowWidth', 594);
Form1.Height := _MemIniU.ReadInteger(SZ_APP_NAME,
'WindowHeight', 342);
end;
Edit1.Text := _MemIniU.ReadString(SZ_APP_NAME, 'UnicodeText', 'ąčę');
finally
_MemIniU.Free;
end;
end;
except
on E: Exception do
MessageDlg(PWideChar(E.Message), TMsgDlgType.mtError,
[TMsgDlgBtn.mbOK], 0);
end;
end;
Procedure TForm1.SaveSettings;
var
_MemIniU: TMemIniFile;
_SettingsPath: string;
begin
try
_SettingsPath := GetHomePath + PathDelim + SZ_APP_NAME + PathDelim;
_MemIniU := TMemIniFile.Create(ChangeFileExt(_SettingsPath, 'Settings.ini'),
TEncoding.UTF8);
try
if Form1.WindowState <> TWindowState.wsMaximized then
begin
_MemIniU.WriteInteger(SZ_APP_NAME, 'WindowLeft', Form1.Left);
_MemIniU.WriteInteger(SZ_APP_NAME, 'WindowTop', Form1.Top);
_MemIniU.WriteInteger(SZ_APP_NAME, 'WindowWidth', Form1.Width);
_MemIniU.WriteInteger(SZ_APP_NAME, 'WindowHeight', Form1.Height);
_MemIniU.WriteString(SZ_APP_NAME, 'UnicodeText', Edit1.Text);
end;
_MemIniU.UpdateFile;
finally
_MemIniU.Free;
end;
except
on E: Exception do
MessageDlg(PWideChar(E.Message), TMsgDlgType.mtError,
[TMsgDlgBtn.mbOK], 0);
end;
end;
Ответ 3
В приложении, где я использовал TIniFile
меня была необходимость начать хранить символы Unicode.
Для этого я просто изменил тип переменной с TIniFile
на TMemIniFile
и в конструкторе после имени файла добавил второй параметр TEncoding.UTF8
. Затем перед освобождением объекта я назвал UpdateFile
. Если файл Ini открыт для чтения, вызов UpdateFile
не требуется.
// ANSI version
var myIniFile: TIniFile;
begin
myIniFIle := TIniFile.Create('c:\Temp\MyFile.ini');
myIniFile.WriteString(par1,par2,par3);
// [...]
myIniFile.Free;
end
// Unicode version
//1) "Mem" added here
var myIniFile: TMemIniFile;
begin
// 2) Enconding added
myIniFIle := TIniFile.Create('c:\Temp\MyFile.ini', TEncoding.UTF8);
myIniFile.WriteString(par1,par2,par3);
// [...]
// 3) call to UpdateFile to save to disc the changes
myIniFile.UpdateFile;
myIniFile.Free;
end
Хорошей новостью является то, что UpdateFile
заставляет INI файл сохраняться с правильной кодировкой, это означает, что если INI файл, закодированный в ANSI
уже существует, он перезаписывается и становится UTF-8
, поэтому транзакция между ANSI
и UTF-8
гладкая и совсем не болезненная.