我开始使用Inno Setup,我的INI文件编码存在一些问题 我想在INI文件中保存用户输入,此输入可以包含重音符。
我使用Inno Setup Unicode,我的setupScript.iss是UTF-8编码的,这是我的代码(部分):
>hihowareyou<
>hihow<
部分中[INI]
Filename: "{app}\www\conf\config.ini"; Section: "Settings"; Key: "ca.plafondAnnuel"; String: "{code:GetUser|Plafond}"
Filename: "{app}\www\conf\config.ini"; Section: "Settings"; Key: "app.siren"; String: "{code:GetUser|Siren}"
Filename: "{app}\www\conf\config.ini"; Section: "Settings"; Key: "app.adresse"; String: "{code:GetUser|Adresse}"
[Code]
var
UserPage: TInputQueryWizardPage;
ExamplePage : TInputOptionWizardPage;
ImmatriculationPage : TInputOptionWizardPage;
FakeElemIndex: Integer;
FakeElem: TCustomEdit;
AdresseTextarea: TNewMemo;
procedure InitializeWizard;
begin
UserPage := CreateInputQueryPage(wpWelcome,
'Configuration de l''application', '',
'Configurez ici votre application. Une fois installée, vous pourrez modifier ces valeurs.');
UserPage.Add('Siren :', False);
UserPage.Add('Plafond annuel (utilisé par les auto-entreprises, mettre 0 si vous ne souhaitez pas plafonner votre chiffre d''affaire.):', False);
FakeElemIndex := UserPage.Add('Votre adresse complète (telle qu''elle s''affichera sur les devis et factures, avec nom complet):', False);
FakeElem := UserPage.Edits[FakeElemIndex];
AdresseTextarea := TNewMemo.Create(WizardForm);
AdresseTextarea.Parent := FakeElem.Parent;
AdresseTextarea.SetBounds(FakeElem.Left, FakeElem.Top, FakeElem.Width, ScaleY(50));
// Hide the original single-line edit
FakeElem.Visible := False;
end;
function GetUser(Param: String): String;
begin
if Param = 'Adresse' then
Result := AdresseTextarea.Text
else if Param = 'Siren' then
Result := UserPage.Values[0]
else if Param = 'Plafond' then
Result := UserPage.Values[1];
end;
返回的值不是UTF-8编码的:我用Notepad ++打开INI文件,我看到该文件是UTF-8编码的。但值getUser|Adresse
是ANSI编码的(如果我将文件的编码更改为ANSI,则此值是可读的)
有人可以帮我理解如何以UTF-8保存此用户输入?
非常感谢!
答案 0 :(得分:2)
Inno Setup([INI]
部分和SetIni*
部分)的INI功能在内部使用Windows API函数WritePrivateProfileString
。
此功能根本不支持UTF-8。它支持的全部是ANSI编码和UTF-16 见How to read/write Chinese/Japanese characters from/to INI files?
因此,如果目标应用程序依赖于Windows API函数来读取它,那么它是否能够读取UTF-8编码的INI文件甚至是个问题。
无论如何,如果您需要UTF-8,您必须自己将条目格式化为INI格式,并使用SaveStringsToUTF8File
function进行编写。
最后一个选项是通过使用系统调用WritePrivateProfileString
来编写看似ANSI编码的字符串,它实际上是UTF-8编码的。
为此,您需要在代码中将字符串转换为UTF-8。您可以使用WideCharToMultiByte
。
function WideCharToMultiByte(CodePage: UINT; dwFlags: DWORD;
lpWideCharStr: string; cchWideChar: Integer; lpMultiByteStr: AnsiString;
cchMultiByte: Integer; lpDefaultCharFake: Integer;
lpUsedDefaultCharFake: Integer): Integer;
external 'WideCharToMultiByte@kernel32.dll stdcall';
const
CP_UTF8 = 65001;
function GetStringAsUtf8(S: string): AnsiString;
var
Len: Integer;
begin
Len := WideCharToMultiByte(CP_UTF8, 0, S, Length(S), Result, 0, 0, 0);
SetLength(Result, Len);
WideCharToMultiByte(CP_UTF8, 0, S, Length(S), Result, Len, 0, 0);
end;
function WritePrivateProfileString(
lpAppName, lpKeyName, lpString, lpFileName: AnsiString): Integer;
external 'WritePrivateProfileStringA@kernel32.dll stdcall';
procedure CurStepChanged(CurStep: TSetupStep);
var
IniFileName: string;
begin
if CurStep = ssInstall then
begin
Log('Writting INI file');
if not ForceDirectories(ExpandConstant('{app}\www\conf')) then
begin
MsgBox('Error creating directory for INI file', mbError, MB_OK);
end
else
begin
IniFileName := ExpandConstant('{app}\www\conf\config.ini');
if (WritePrivateProfileString(
'Settings', 'ca.plafondAnnuel', GetStringAsUtf8(GetUser('Plafond')),
IniFileName) = 0) or
(WritePrivateProfileString(
'Settings', 'app.siren', GetStringAsUtf8(GetUser('Siren')),
IniFileName) = 0) or
(WritePrivateProfileString(
'Settings', 'app.adresse', GetStringAsUtf8(GetUser('Adresse')),
IniFileName) = 0) then
begin
MsgBox('Error writting the INI file', mbError, MB_OK);
end;
end;
end;
end;