【问题标题】:Writing a string to a TFileStream in Delphi 2010在 Delphi 2010 中将字符串写入 TFileStream
【发布时间】:2009-09-16 17:32:25
【问题描述】:

我的 Delphi 2007 代码如下所示:

procedure WriteString(Stream: TFileStream; var SourceBuffer: PChar; s: string);
begin
  StrPCopy(SourceBuffer,s);
  Stream.Write(SourceBuffer[0], StrLen(SourceBuffer));
end;

我这样称呼它:

var
  SourceBuffer : PChar;
  MyFile: TFileStream;

....

SourceBuffer := StrAlloc(1024);
MyFile := TFileStream.Create('MyFile.txt',fmCreate);
WriteString(MyFile,SourceBuffer,'Some Text');
....

这在 Delphi 2007 中有效,但在 Delphi 2010 中给了我很多垃圾字符。我知道这是由于 unicode 合规性问题,但我不知道如何解决这个问题。

这是我迄今为止尝试过的:

  • 更改数据类型 SourceBuffer(以及参数 WideString 预期)到 PWideChar

  • suggestions listed here中的每一位

我做错了什么?

【问题讨论】:

    标签: delphi unicode delphi-2010 delphi-2007


    【解决方案1】:

    您不需要单独的缓冲区来将字符串写入流。可能最简单的方法是将字符串编码为 UTF8,如下所示:

    procedure TStreamEx.writeString(const data: string);
    var
       len: cardinal;
       oString: UTF8String;
    begin
       oString := UTF8String(data);
       len := length(oString);
       self.WriteBuffer(len, 4);
       if len > 0 then
          self.WriteBuffer(oString[1], len);
    end;
    
    function TStreamEx.readString: string;
    var
       len: integer;
       iString: UTF8String;
    begin
       self.readBuffer(len, 4);
       if len > 0 then
       begin
          setLength(iString, len);
          self.ReadBuffer(iString[1], len);
          result := string(iString);
       end;
    end;
    

    我已将 TStreamEx 声明为 TStream 的类助手,但将它们重写为一个单独的过程并像您的示例一样运行应该不会太难。

    【讨论】:

    • 在我删除“self.WriteBuffer(len, 4);”后这对我有用- 那是在输出文件中写入一些乱码。
    • 那些“乱码”是字符串的长度,所以读取函数知道要读回多少。如果你需要它是纯文本,你需要一些其他的方式来告诉readString 在哪里停止。
    • 我正在写这个文件供另一个应用程序读入,所以我能否读回它并不重要。
    • 在这种情况下,请确保其他应用程序知道它正在接收 UTF8 格式的字符串。或者,如果您无法控制其他应用程序,请将其转换为 AnsiString 而不是 UTF8String。但是,如果您使用 ANSI 集之外的 Unicode 字符,则可能会丢失数据。
    • 请补充说明它是长度的前缀,我也是用它来输出一个文本文件,不知道长度的前4个字节。
    【解决方案2】:

    Delphi 2010 有一个很好的解决方案,记录在这里:

    http://docwiki.embarcadero.com/CodeExamples/en/StreamStrRdWr_%28Delphi%29

    var
      Writer: TStreamWriter;
    ...
    
      { Create a new stream writer directly. }
      Writer := TStreamWriter.Create('MyFile.txt', false, TEncoding.UTF8);
      Writer.Write('Some Text');
    
      { Close and free the writer. }
      Writer.Free();
    

    【讨论】:

    • 链接已损坏。看起来像这个:docwiki.embarcadero.com/CodeExamples/en/…
    • 约翰,感谢您更正链接。看起来违反了网站的黄金法则——永远不要破坏永久链接。特别是对于像这样的微不足道的 url 重命名。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多