【问题标题】:Inno Setup - Convert array of string to Unicode and back to ANSIInno Setup - 将字符串数组转换为 Unicode 并返回 ANSI
【发布时间】:2018-02-25 16:57:32
【问题描述】:

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

目前我有两个问题:

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

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

【问题讨论】:

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


    【解决方案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;
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-09
      • 2019-03-28
      • 2013-08-21
      • 2013-02-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-27
      相关资源
      最近更新 更多