Inno Setup - 将字符串数组转换为 Unicode 并返回到 ANSI

Inno Setup - Convert array of string to Unicode and back to ANSI

我正在将朝鲜语 CP51949 (EUC-KR) 编码的 ANSI 文件加载到字符串数组 (LoadStringsFromFile) 中。我的系统和预期的最终用户系统没有将 CP51949 设置为传统的非 Unicode 编码。

目前我有两个问题:

  1. 除非我 运行 带有 Locale Emulator 的应用程序(这很烦人,因为设置本身只有英文),韩文文本显示为乱码。
  2. Pos 给出了错误的结果并且 StringChange 完全失败,除非我切换到 String,执行操作,然后返回 AnsiString

所以,我想知道是否有办法将数组转换为 unicode,然后在保存之前返回。

要将以特定 Ansi 编码编码的文件转换为 Unicode string (UTF-16 LE),请使用 MultiByteToWideChar function:

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

function LoadStringFromFileInCP(
  FileName: string; var S: string; CP: Integer): Boolean;
var
  Ansi: AnsiString;
  Len: Integer;
begin
  Result := LoadStringFromFile(FileName, Ansi);
  if Result then
  begin
    Len := MultiByteToWideChar(CP, 0, Ansi, Length(Ansi), S, 0);
    SetLength(S, Len);
    MultiByteToWideChar(CP, 0, Ansi, Length(Ansi), S, Len);
  end;
end;

function LoadStringsFromFileInCP(
  FileName: string; Strings: TStrings; CP: Integer): Boolean;
var
  S: string;
begin
  Result := LoadStringFromFileInCP(FileName, S, CP);
  if Result then Strings.Text := S;
end;

(请注意,我使用 TStrings 来存储 strings/lines 集合而不是 TArrayOfString,因为 TStrings 更易于使用)


要将 Unicode string 转换回 Ansi,请使用 WideCharToMultiByte function:

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 SaveStringToFileInCP(FileName: string; S: string; CP: Integer): Boolean;
var
  Ansi: AnsiString;
  Len: Integer;
begin
  Len := WideCharToMultiByte(CP, 0, S, Length(S), Ansi, 0, 0, 0);
  SetLength(Ansi, Len);
  WideCharToMultiByte(CP, 0, S, Length(S), Ansi, Len, 0, 0);
  Result := SaveStringToFile(FileName, Ansi, False);
end;

function SaveStringsToFileInCP(
  FileName: string; Strings: TStrings; CP: Integer): Boolean;
begin
  Result := SaveStringToFileInCP(FileName, Strings.Text, CP);
end;

使用如下函数:

const
  CP_EUC_KOREAN = 51949;

var
  I: Integer;
  Strings: TStrings;
begin
  Strings := TStringList.Create;
  if LoadStringsFromFileInCP('korean.txt', Strings, CP_EUC_KOREAN) then
  begin
    for I := 0 to Strings.Count - 1 do
    begin
      MsgBox(Strings[I], mbInformation, MB_OK);
    end;
  end;

  SaveStringsToFileInCP('korean_out.txt', Strings, CP_EUC_KOREAN);
end;

在我的纯英文系统上正常工作: