Filestream.WriteBuffer方法中隐含的具有字符串到缓冲区void类型转换的额外空间



我已经有一段时间不需要在这里发帖了,但我在实现文件流时遇到了问题。当将字符串写入文件流时,结果文本文件在每个字符之间插入了额外的空格

因此,当运行此方法时:

Function TDBImportStructures.SaveIVDataToFile(const AMeasurementType: integer;
  IVDataRecordList: TIV; ExportFileName, LogFileName: String;
  var ProgressInfo: TProgressInfo): Boolean; // AM
var
  TempString: unicodestring;
  ExportLogfile, OutputFile: TFileStream;
begin
  ExportLogfile := TFileStream.Create(LogFileName, fmCreate);
  TempString :=
    'FileUploadTimestamp, Filename, MeasurementTimestamp, SerialNumber, DeviceID, PVInstallID,'
    + #13#10;
  ExportLogfile.WriteBuffer(TempString[1], Length(TempString) * SizeOf(Char));
  ExportLogfile.Free;
  OutputFile := TFileStream.Create(ExportFileName, fmCreate);
  TempString :=
    'measurementdatetime,closestfiveseconddatetime,closesttenminutedatetime,deviceid,'
    + 'measuredmoduletemperature,moduletemperature,isc,voc,ff,impp,vmpp,iscslope,vocslope,'
    + 'pvinstallid,numivpoints,errorcode' + #13#10;
  OutputFile.WriteBuffer(TempString[1], Length(TempString) * SizeOf(Char));
  OutputFile.Free;
end;

(这是一种精简的测试方法,只写标题)。"OutPutFile"的csv文件读取

当在写字板中查看时,而不是在excel、记事本等中查看。我猜SizeOf(Char)语句在unicode上下文中是错误的,但我不确定在这里插入什么是正确的。"ExportLogfile"似乎工作正常,但"OutPutFile"不正常

从我在其他地方读到的内容来看,这就是问题所在;不是写字板,请参阅http://social.msdn.microsoft.com/Forums/en-US/7e040fd1-f399-4fb1-b700-9e7cc6117cc4/unicode-to-files-and-console-vs-notepad-wordpad-word-etc?forum=vcgeneral

有什么建议吗?非常感谢,Brian

您正在编写16位UTF-16编码字符。然后将文本视为ANSI编码的文本。这种不匹配解释了这种行为。事实上,您没有额外的空格,这些空格是零字节,被解释为空字符。

您需要决定要使用哪种编码。哪些程序将读取该文件?他们期望使用哪种文本编码?很少有读取csv文件的程序能够理解UTF-16。

一个快速的解决方案是切换到使用AnsiString,这将导致8位文本。但不支持国际文本。你需要支持国际文本吗?那么也许您需要UTF-8。同样,您可以使用Utf8String执行快速修复,但我认为您应该深入研究。

处理文本到二进制的转换是很奇怪的。使用TStringList会简单得多,调用Add来添加行,然后在保存文件时指定编码。

List.Add(...);
List.Add(...);
// etc. 
List.SaveToFile(FileName, TEncoding.UTF8);

也许更优雅的方法是使用TStreamWriter类。创建对象时提供输出流(或文件名)和编码。然后调用WriteWriteLine添加文本。

Writer := TStreamWriter.Create(FileName, TEncoding.UTF8);
try
  Writer.WriteLine(...);
  // etc. 
finally
  Writer.Free;
end;

我在这里假设了UTF-8,但您可以很容易地指定不同的编码。

最新更新