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

时间:2017-09-16 19:11:51

标签: unicode character-encoding inno-setup pascal codepages

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

目前我有两个问题:

  1. 除非我使用Locale Emulator运行应用程序(这很烦人,因为设置本身只有英文版),韩文文本显示为乱码。
  2. Pos提供了错误的结果,StringChange完全失败,除非我切换到String,执行操作,然后返回AnsiString
  3. 所以,我想知道是否有办法将数组转换为unicode,然后在保存之前返回。

1 个答案:

答案 0 :(得分:1)

要将以特定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来存储字符串/行集合而不是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;

在我的英语系统上正常运行:

enter image description here enter image description here