使用普通csv文件在TStreamReader中编码问题

时间:2015-03-10 09:14:44

标签: delphi delphi-xe

我在阅读使用Excel 2013生成的普通csv文件时遇到问题。似乎编码在TStreamReader类中无法正常工作。奇怪的是,一个文件正在处理另一个文件而不是。读取第二个文件时,TStreamReader返回一个空字符串:

LString := FEncoding.GetString(LBuffer, StartIndex, ByteBufLen);

两个文件都具有1字节ANSI编码。但是TStreamReader正在使用UTF8编码。

我的代码:

  fs := TFileStream.Create(aFileName, fmOpenRead or fmShareDenyNone);
  sr := TStreamReader.Create(fs);
  while (not sr.EndOfStream) do //sr.EndOfStream is always true!!!!
  begin
    //some code here
  end;

到目前为止,我发现,以下函数返回一个空字符串:

function TMBCSEncoding.GetCharCount(Bytes: PByte; ByteCount: Integer): Integer;
begin
  Result := UnicodeFromLocaleChars(FCodePage, FMBToWCharFlags,
    PAnsiChar(Bytes), ByteCount, nil, 0);
end;

当我比较两个文件时,它们在Bytes和ByteCount变量旁边具有相同的输入。但是字节以相同的值(相同的csv头名称)开始。

所以我的问题是,为什么一个文件正常工作而另一个文件没有?如何正确读取文件?

1 个答案:

答案 0 :(得分:2)

您调用的TStreamReader的构造函数是这样的:

constructor TStreamReader.Create(Stream: TStream);
begin
  Create(Stream, TEncoding.UTF8, True);
end;

True参数为DetectBOM。如果遇到BOM,将确定编码。否则,该文件将被视为UTF-8。您的文件没有BOM。因此,你得到了你所要求的。即该文件被视为UTF-8。

如果您希望将文件视为ANSI,则必须指定编码:

sr := TStreamReader.Create(fs, TEncoding.Default);

或者如果您想在没有找到BOM的情况下默认为ANSI,否则请尊重BOM,您可以这样做:

sr := TStreamReader.Create(fs, TEncoding.Default, True);

为什么您的代码适用于一个文件但不适用于另一个文件?据推测,一个文件完全在ASCII范围内,另一个文件在该范围之外。 UTF-8在单个字节中对ASCII范围内的字符进行编码,这意味着ASCII编码文件可以通过UTF-8编码正确解释。这是UTF-8的主要设计目标之一。