0

I have a UTF-8 encoding .INI file, during the installation the users will write a name with symbols and codes that will be written to the .INI file, after finishing or during the installation it will be able to convert that UTF- 8 to ANSI?

I can not process the file in ANSI from the beginning because the codes and symbols are not recognized in the program

This displays the name processing the file with ANSI from the beginning, when in fact it is: WILLIAMS117 ™

This displays the name processing the file with ANSI from the beginning, when in fact it is: WILLIAMS117 ™

Community
  • 1
  • 1
  • *"are not recognized in the program"* - What program? – Martin Prikryl Nov 21 '16 at 07:02
  • *"written to the .INI file"* - How do you write UTF-8 INI file in Inno Setup? Why don't you write it in Ansi directly? – Martin Prikryl Nov 21 '16 at 07:07
  • @MartinPrikryl Is actually a game, you need a file called "rev.ini" this should be in ANSI format, the game needs a name for the user, but when users insert the name with signs and codes in the game does not recognize them And shows them as in the previous image, so you need to write it in "rev.ini" in UTF-8 format and then convert it to ANSI. Sorry for my english I'm Latin American and use google translate – Williams Mogollon Nov 21 '16 at 15:27
  • You didn't answer my questions. How do you create the INI file? The Inno Setup INI functions actually write the INI file in Ansi encoding. So I wonder, how did you even got to your problem with having INI file with UTF-8 encoding. – Martin Prikryl Nov 21 '16 at 15:30
  • @MartinPrikryl The INI file does not create innosetup, it only writes the values, I have it already created in UTF-8 encoding, if it can not innosetup convert it to ANSI after the installation, can it be any other way or some external program? – Williams Mogollon Nov 21 '16 at 17:30
  • 1) So why didn't you create the file in Ansi encoding? 2) You still did not answer, how do you write the values in UTF-8 encoding to the INI file. 3) I've shown you, how to convert the INI file to UTF-8 encoding in my answer! So why do you ask, if there's another way? – Martin Prikryl Nov 21 '16 at 21:13
  • Sorry but I thought that innosetup could make it easier but I found a program that can convert UTF-8 to ANSI, it is called "ICONV", its code was used to write the values, thanks – Williams Mogollon Nov 21 '16 at 23:53

1 Answers1

1

If the file has UTF-8 BOM, it's easy, use the LoadStringsFromFile to load the file and the SaveStringsToFile to save it back in Ansi encoding:

function ConvertFileFromUTF8ToAnsi(FileName: string): Boolean;
var
  Lines: TArrayOfString;
begin
  Result :=
    LoadStringsFromFile(FileName, Lines) and
    SaveStringsToFile(FileName, Lines, False);
end;

If the file does not have UTF-8 BOM, you have to convert it on your own:

function WideCharToMultiByte(
  CodePage: UINT; dwFlags: DWORD; lpWideCharStr: string; cchWideChar: Integer;
  lpMultiByteStr: AnsiString; cchMultiByte: Integer;
  lpDefaultCharFake: Integer; lpUsedDefaultCharFake: Integer): Integer;
  external 'WideCharToMultiByte@kernel32.dll stdcall';

function MultiByteToWideChar(
  CodePage: UINT; dwFlags: DWORD; const lpMultiByteStr: AnsiString; cchMultiByte: Integer; 
  lpWideCharStr: string; cchWideChar: Integer): Integer;
  external 'MultiByteToWideChar@kernel32.dll stdcall';  

const
  CP_ACP = 0;
  CP_UTF8 = 65001;

function ConvertFileFromUTF8ToAnsi(FileName: string): Boolean;
var
  S: AnsiString;
  U: string;
  Len: Integer;
begin
  Result := LoadStringFromFile(FileName, S);
  if Result then
  begin
    Len := MultiByteToWideChar(CP_UTF8, 0, S, Length(S), U, 0);
    SetLength(U, Len);
    MultiByteToWideChar(CP_UTF8, 0, S, Length(S), U, Len);
    Len := WideCharToMultiByte(CP_ACP, 0, U, Length(U), S, 0, 0, 0);
    SetLength(S, Len);
    WideCharToMultiByte(CP_ACP, 0, U, Length(U), S, Len, 0, 0);

    Result := SaveStringToFile(FileName, S, False);
  end;
end;

You can of course also use an external utility. Like PowerShell:

powershell.exe -ExecutionPolicy Bypass -Command [System.IO.File]::WriteAllText('my.ini', [System.IO.File]::ReadAllText('my.ini', [System.Text.Encoding]::UTF8), [System.Text.Encoding]::Default)

If you cannot to rely on the end-user to have the intended Ansi encoding set as legacy in Windows, you have to specify it explicitly, instead of using CP_ACP. See:
Inno Setup - Convert array of string to Unicode and back to ANSI.

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992