【问题标题】:How do I get Delphi 2006 TStringList.LoadFromFile to load UTF-16 files如何让 Delphi 2006 TStringList.LoadFromFile 加载 UTF-16 文件
【发布时间】:2011-09-24 18:03:50
【问题描述】:

我有一个 Delphi 2006 应用程序,我正在添加代码来处理一些生成的 CSV 数据文件。 TStringList.LoadFromFile 给出了奇怪的结果,我刚刚发现文件是 UTF-16 编码的。

计划升级到 XE,但目前不可行。

用 D2006 处理这些文件的最简单方法是什么?我假设它们可以毫无问题地映射到 8 位 ASCII - 它们是“纯” CSV - 只是数字和逗号等,我认为不在 8 中的字符不会有任何问题-位设置。

【问题讨论】:

    标签: delphi character-encoding ascii utf-16 delphi-2006


    【解决方案1】:

    TStringList 在 D2006 中不支持 UTF-16,因此您必须手动加载和解码文件数据,然后才能将输出放入您的 TStringList。例如:

    var
      sl: TStringList;
      {$IFNDEF D2009_OR_LATER}
      ms: TMemoryStream;
      ptr: PWideChar;
      s: AnsiString;
      dlen, slen: Integer;
      {$ENDIF}
    begin
      ...
      {$IFDEF D2009_OR_LATER}
      sl.LoadFromFile('...', TEncoding.Unicode);
      {$ELSE}
      ms := TMemoryStream.Create;
      try
        ms.LoadFromFile('...');
        ptr := PWideChar(ms.Memory);
        dlen := ms.Size div SizeOf(WideChar);
        if (dlen >= 1) and (PWord(ptr)^ = $FEFF) then
        begin
          Inc(ptr);
          Dec(dlen);
        end;
        slen := WideCharToMultiByte(0, 0, ptr, dlen, nil, 0, nil, nil);
        if slen > 0 then begin
          SetLength(s, slen);
          WideCharToMultiByte(0, 0, ptr, dlen, PAnsiChar(s), slen, nil, nil));
        end;
        sl.Text := s;
      finally
        ms.Free;
      end;
      {$ENDIF}
      ...
    end;
    

    【讨论】:

    • 谢谢@Remy。您的示例有效,但文件包含 BOM 标头 $FF $FE (所以我最终添加了一个“?”作为第一个字符串的第一个字符)并且我不确定从第二个字符引用的正确方法到流的末尾。?
    • 您必须将TMemoryStream.Memory 指针分配给局部变量,然后根据需要推进它。我已经编辑了示例以显示这一点。
    【解决方案2】:

    以防万一有数据丢失的风险,您可以尝试使用JCLTJclWideStringList。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-10-10
      • 1970-01-01
      • 1970-01-01
      • 2020-11-07
      • 2015-05-14
      • 2015-07-14
      相关资源
      最近更新 更多