(Wide)String - storing in TFileStream, Delphi 7. What is the fastest way?

前端 未结 4 1042
[愿得一人]
[愿得一人] 2021-01-02 23:28

I\'m using Delphi7 (non-unicode VCL), I need to store lots of WideStrings inside a TFileStream. I can\'t use TStringStream as the (wide)strings are mixed with binary data, t

4条回答
  •  小鲜肉
    小鲜肉 (楼主)
    2021-01-02 23:52

    Rather than read and write one character at a time, read and write them all at once:

    procedure WriteWideString(const ws: WideString; stream: TStream);
    var
      nChars: LongInt;
    begin
      nChars := Length(ws);
      stream.WriteBuffer(nChars, SizeOf(nChars);
      if nChars > 0 then
        stream.WriteBuffer(ws[1], nChars * SizeOf(ws[1]));
    end;
    
    function ReadWideString(stream: TStream): WideString;
    var
      nChars: LongInt;
    begin
      stream.ReadBuffer(nChars, SizeOf(nChars));
      SetLength(Result, nChars);
      if nChars > 0 then
        stream.ReadBuffer(Result[1], nChars * SizeOf(Result[1]));
    end;
    

    Now, technically, since WideString is a Windows BSTR, it can contain an odd number of bytes. The Length function reads the number of bytes and divides by two, so it's possible (although not likely) that the code above will cut off the last byte. You could use this code instead:

    procedure WriteWideString(const ws: WideString; stream: TStream);
    var
      nBytes: LongInt;
    begin
      nBytes := SysStringByteLen(Pointer(ws));
      stream.WriteBuffer(nBytes, SizeOf(nBytes));
      if nBytes > 0 then
        stream.WriteBuffer(Pointer(ws)^, nBytes);
    end;
    
    function ReadWideString(stream: TStream): WideString;
    var
      nBytes: LongInt;
      buffer: PAnsiChar;
    begin
      stream.ReadBuffer(nBytes, SizeOf(nBytes));
      if nBytes > 0 then begin
        GetMem(buffer, nBytes);
        try
          stream.ReadBuffer(buffer^, nBytes);
          Result := SysAllocStringByteLen(buffer, nBytes)
        finally
          FreeMem(buffer);
        end;
      end else
        Result := '';
    end;
    

    Inspired by Mghie's answer, have replaced my Read and Write calls with ReadBuffer and WriteBuffer. The latter will raise exceptions if they are unable to read or write the requested number of bytes.

提交回复
热议问题