如何让Delphi 2006 TStringList.LoadFromFile加载UTF-16文件

如何让Delphi 2006 TStringList.LoadFromFile加载UTF-16文件,delphi,character-encoding,ascii,utf-16,delphi-2006,Delphi,Character Encoding,Ascii,Utf 16,Delphi 2006,我有一个Delphi2006应用程序,我正在添加代码来处理一些生成的CSV数据文件。TStringList.LoadFromFile给出了奇怪的结果,我刚刚发现这些文件是UTF-16编码的 计划升级到XE,但目前不是一个选项 用D2006处理这些文件最简单的方法是什么?我假设它们可以映射到8位ASCII而没有任何问题-它们是“纯”CSV-只有数字和逗号等。我认为8位集合之外的字符不会有任何问题。TStringList在D2006中不支持UTF-16,因此,在将输出放入TStringList之前,

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

计划升级到XE,但目前不是一个选项


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

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;

为了防止数据丢失,您可以尝试使用TJclWideStringList。

谢谢@Remy。您的示例可以工作,但该文件包含BOM表标题$FF$FE(因此我最后添加了一个“?”作为第一个字符串的第一个字符)我不确定从第二个字符引用到流末尾的正确方法。您必须将
TMemoryStream.Memory
指针指定给局部变量,然后根据需要将其推进。我已经编辑了这个示例来说明这一点。