utf-8 - 使用 Inno Setup 创建无 BOM 的 UTF8 文件(Unicode 版本)

标签 utf-8 text-files inno-setup

我必须读取和修改一些 JSON 文件。文件编码必须为UTF8无BOM,否则JSON文件将不被接受。

我尝试了以下代码:

const
    Utf8Bom     = #$EF#$BB#$BF;
    Utf16BomLE  = #$FF#$FE;                 // little endian // 
    Utf16BomBE  = #$FE#$FF;                 // big endian // 
    Utf16Bom    = Utf16BomBE;
    CP_UTF16    = 1200;
    CP_UTF8     = 65001;

function WideStringToString (const wStr: string; codePage: Word): string;
var
    len: Integer;
begin
    len := WideCharToMultiByte (codePage, 0, wStr, -1, '', 0, 0, 0);
    if len > 0 then
    begin
        SetLength (Result, len-1);
        WideCharToMultiByte (codePage, 0, wStr, -1, Result, Length (Result), 0,  0);
    end;
end;

function ClearBom(const s, sig: string): string;
var
    i, n, len: Integer;
begin
    Result := s;
    len := Length (sig);
    n := 0;
    if (len> 0) and (Length (Result)> len) then
        repeat
            for i := 1 to len do
                if Result [1] = sig [i] then
                begin
                    Delete (Result, 1, 1);
                    Break;
                end;
            n := n + 1;
        until (n = len) or (Result = '');
end;

function ConvertUtf16(const SourceStr: string; codePage: Word): string;
var
    wStr: string;
begin
    try
        wStr := ClearBom(SourceStr, Utf16Bom);
        Result := WideStringToString(wStr, codePage);
    finally
        SetLength(wStr, 0);
    end;
end;

function Utf16ToUtf8(const SourceStr: string): string;
begin
    Result := ConvertUtf16(SourceStr, CP_UTF8);
end;

function JSONSaveFile(const Filename: String; s: String): Boolean;
var
    fs: TFileStream;
    i, len : Integer;
begin
    i := 1;
    len := Length(s)
    If len > 0 then
    begin
        try
            try
                fs := TFileStream.Create(Filename, fmCreate or f mShareExclusive);
                fs.Seek(0, 0);
                while (s[i] <> #0) and (i < len) do
                begin
                    fs.WriteBuffer(s[i],CharLength(s,i));
                    i := i + CharLength(s,i);
                end;
                Result := True;
            except
                Log('EXCEPTION RAISED in JSONSaveFile: '+Filename);
            end;
        finally
            fs.free;
        end;
    end;
end;

我只得到 ANSI 编码的文件。 SaveStringsToUTF8File() 等内置函数将不起作用,因为默认情况下会添加 BOM。

或者是使用 SaveStringToFile() 保存/创建此文本文件的更好方法?

如何解决?

最佳答案

使用WideCharToMultiByte function将字符串转换为 UTF-8 并保存:

const
  CP_UTF8 = 65001;

function WideCharToMultiByte(CodePage: UINT; dwFlags: DWORD;
  lpWideCharStr: string; cchWideChar: Integer; lpMultiByteStr: AnsiString;
  cchMultiByte: Integer; lpDefaultCharFake: Integer;
  lpUsedDefaultCharFake: Integer): Integer;
  external '<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="a0f7c9c4c5e3c8c1d2f4cfedd5ccd4c9e2d9d4c5e0cbc5d2cec5cc93928ec4cccc" rel="noreferrer noopener nofollow">[email protected]</a> stdcall';

function GetStringAsUtf8(S: string): AnsiString;
var
  Len: Integer;
begin
  Len := WideCharToMultiByte(CP_UTF8, 0, S, Length(S), Result, 0, 0, 0);
  SetLength(Result, Len);
  WideCharToMultiByte(CP_UTF8, 0, S, Length(S), Result, Len, 0, 0);
end;

function SaveStringToUTF8FileWithoutBOM(FileName: string; S: string): Boolean;
var
  Utf8: AnsiString;
begin
  Utf8 := GetStringAsUtf8(S);
  Result := SaveStringToFile(FileName, Utf8, False);
end;

您必须使用Unicode version of Inno Setup (Inno Setup 6 以来的唯一版本)。


另请参阅:

关于utf-8 - 使用 Inno Setup 创建无 BOM 的 UTF8 文件(Unicode 版本),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36876001/

相关文章:

java - Windows 上的 UTF-8/ISO-8859-1 编码问题 --> Unix

c - 在 C 中打印 UTF-8 字符串的字节

c# - 如何从文本文件中固定这个解析循环

c++ - 按文本搜索行并将其删除到文本文件中(从 C# 到 C++/CLI)

inno-setup - Inc 函数 Inno Setup

inno-setup - 在 Inno Setup 中逐行读取文本文件

Android 4.0 html 编码在 web View 中崩溃

mysql - Unicode字符在MySql和Oracle中的存储

python - 在python中处理大文本文件

.net - 有人知道 Inno Setup 的可靠 .NET Framework 2.0 安装程序脚本吗?