2016-10-04 112 views
4

我有一个从Resource Hacker导出的.inf文件。该文件采用UTF-16 LE编码。Inno Setup Pascal脚本 - 读取UTF-16文件

EXTRALARGELEGENDSII_INI TEXTFILE "Data.bin" 

LARGEFONTSLEGENDSII_INI TEXTFILE "Data_2.bin" 

NORMALLEGENDSII_INI TEXTFILE "Data_3.bin" 

THEMES_INI TEXTFILE "Data_4.bin" 

当我使用LoadStringFromFile function加载:

procedure LoadResources; 
var 
    RESOURCE_INFO: AnsiString; 
begin 
    LoadStringFromFile(ExpandConstant('{tmp}\SKINRESOURCE - INFO.inf'), RESOURCE_INFO); 
    Log(String(RESOURCE_INFO)); 
end; 

我在调试输出得到这个:

E 

请告诉我如何解决这个问题。

在此先感谢。

回答

0

看起来您正在尝试登录的文件是Windows Unicode(UTF-16LE)编码的文本文件。

您可以使用命令行iConv并将您的文件转换为Windows UTF-8编码文件。

LoadStringFromFile Support Function不能很好地加载Unicode字符串,它只支持加载ANSI和UTF-8编码文本文件。

Inno Setup Compiler调试输出停止记录文本文件,因为它找到了一个无法加载的字符(NULL),这就是为什么在编译调试输出中只有“E”,即使LoadStringFromFile完全加载文本文件。


您需要下载ICONV的安装程序如下图所示得到ICONV可执行文件和使用的一些DLL文件的字符编码之间的转换。

enter image description here

下载后,安装的GnuWin32(libiconv的适用于Windows)并进入安装文件夹。

将以下四个文件复制到名为“bin”的安装文件夹的子目录中。

它们是:

libcharset1.dll

libiconv2。dll的

iconv.exe

libintl3.dll

这些文件复制到存储您的Inno Setup的项目文件的目录。

然后使用以下代码进行转换。

[Files] 
Source: "libcharset1.dll"; Flags: dontcopy 
Source: "iconv.exe"; Flags: dontcopy 
Source: "libiconv2.dll"; Flags: dontcopy 
Source: "libintl3.dll"; Flags: dontcopy 

[Code] 
function InitializeSetup(): Boolean 
var 
    ErrorCode: Integer; 
begin 
    ExtractTemporaryFile('iconv.exe'); 
    ExtractTemporaryFile('libcharset1.dll'); 
    ExtractTemporaryFile('libintl3.dll'); 
    ExtractTemporaryFile('libiconv2.dll'); 
    ShellExec('Open', ExpandConstant('CMD.exe'), ExpandConstant('/C iConv -f UTF-16LE -t UTF-8 < SKINRESOURCE-INFO.inf > SKINRESOURCE-INFO-ANSI.inf'), ExpandConstant('{tmp}'), SW_HIDE, ewWaitUntilTerminated, ErrorCode); 
    DeleteFile(ExpandConstant('{tmp}\SKINRESOURCE-INFO.inf')); 

现在LoadStringFromFile应该正确像现在加载文本文件,它具有Windows的UTF-8编码。

如果您使用的是Unicode Inno Setup,您也可以在将其转换为Unicode字符串(如Log(String(RESOURCE_INFO)))后将其记录下来。

+0

谢谢!奇迹般有效! – Blueeyes789

+0

1)为什么选择ANSI?你以这种方式丢失了Unicode字符。使用UTF-8! 2)并注意ANSI与Windows-1252不一样。 ANSI编码的使用与Windows配置不同。因此,如果您明确转换为Windows-1252,但使用配置的ANSI编码加载文件,则最终会出现乱码,除非该文件仅使用ASCII字符。 3)您可以[使用PowerShell转换编码](http://stackoverflow.com/a/4817683/850848),不需要第三方工具。但无论如何,你甚至不需要任何外部工具。你可以在Pascal脚本中进行转换。 –

+0

@MartinPrikryl纠正为UTF-8。我忘记了PowerShell。 :-( – GTAVLover

3

该文件采用UTF-16 LE编码。

LoadStringFromFile不支持任何Unicode编码。它将文件原样加载到字节数组(AnsiString被有效地用作字节数组)。

由于Unicode string实际上使用UTF-16 LE编码,所以您只需将位数据按位复制到(Unicode)string即可。并修剪UTF-16 LE BOMFEFF)。

procedure RtlMoveMemory(Dest: string; Source: PAnsiChar; Len: Integer); 
    external '[email protected] stdcall'; 

function LoadStringFromUTF16LEFile(FileName: string; var S: string): Boolean; 
var 
    A: AnsiString; 
begin 
    Result := LoadStringFromFile(FileName, A); 
    if Result then 
    begin 
    SetLength(S, Length(A) div 2); 
    RtlMoveMemory(S, A, Length(S) * 2); 
    { Trim BOM, if any } 
    if (Length(S) >= 1) and (Ord(S[1]) = $FEFF) then 
     Delete(S, 1, 1); 
    end; 
end; 

参见Inno Setup Reading file in Ansi and Unicode encoding

+0

什么?我认为这种转换是不可能的。谢谢你的答案,我想知道哪些函数支持Unicode编码。 :-) – Blueeyes789

+0

对不起。我在这里寻求帮助。忽略之前的评论。 :-( – GTAVLover

+0

请参阅[Inno安装读取Ansi和Unicode编码文件](http://stackoverflow.com/q/38968230/850848)。 –

相关问题