Write to a string from a MemoryStream ? lazarus / 21-General ---------------------------------------------------------------------- dbannon · 2021-03-10 05:11 I (think I) have a valid memorystream with some content and I want that content in a normal ansistring. The RTL docs indicate that there is a means to write a shortstring (StrRead;) but no ANSIString, but I find reference to ReadANSIString in the forum.   However, seems I am not using it as I would expect. Anyone suggest how I should fill our a string with whatever is in the stream ? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i         AStream := TMemoryStream.Create;            // grab an RTF version of what was selected.        try            KMemo1.SaveToRTFStream(AStream, True);                // This puts some data into the stream (I think).            AStream.Seek(0, soBeginning);            if AStream.Size > 0 then            Overwritten := AStream.ReadANSIString();      // Overwritten is an ANSI String.  Generates a stream read error        finally            AStream.Free;        end; Thanks, Davo ---------------------------------------------------------------------- balazsszekely · 2021-03-10 05:35 Hi Davo, Please try this: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var  AStream: TMemoryStream;  Overwritten: AnsiString;begin  Overwritten := '';  AStream := TMemoryStream.Create;  try    KMemo1.SaveToRTFStream(AStream, True, True);    if AStream.Size > 0 then    begin      AStream.Seek(0, soBeginning);      SetLength(Overwritten, AStream.Size);      AStream.ReadBuffer(Pointer(Overwritten)^, AStream.Size);    end;  finally    AStream.Free;  end;  ShowMessage(Overwritten);end; PS: You must select something in KMemo, because ASelectedOnly is true. ---------------------------------------------------------------------- lucamar · 2021-03-10 06:15 ReadANSIString() is a utility function designed to read back strings as written by WriteANSIString(), that is: first a DWord with the length of the string and then the string contents. It doesn't work to read arbitrary strings by themselves. As an alternative to GetMem's solution, you could use an intermediate TStringStream: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i function StreamToString(const AStream: TStream): String;begin  Result := '';  with TStringStream.Create() do   try    LoadFromStream(AStream);    Result := DataString;  finally    Free;  end;end; This works quite well for most types of stream and will fail only with source streams where Size can't be determined beforehand. ---------------------------------------------------------------------- dbannon · 2021-03-10 06:54 This list is Brilliant ! Thanks getmem and lucamar.  I tried getmem's method, works perfectly.  But I must admit, I would never have dreamed of applying setlength() to a managed object like ANSIString !   (I went for getmem's method rather than add a new type to my binary) Now, I note no mention of AStream.ReadBuffer(..) in https://www.freepascal.org/docs-html/rtl/objects/tmemorystream.html nor the TStream page.  Wonder why ?   No wiki page on streams either ... Anyway, I'm happy, thanks. Davo ---------------------------------------------------------------------- lucamar · 2021-03-10 07:37 Quote from: dbannon on March 10, 2021, 07:54:59 amNow, I note no mention of AStream.ReadBuffer(..) in https://www.freepascal.org/docs- html/rtl/objects/tmemorystream.html nor the TStream page.  Wonder why ? Huh? It's there alright: TStream.ReadBuffer. You were looking at the docs for old-style Objects instead of modern Classes ---------------------------------------------------------------------- PascalDragon · 2021-03-10 07:59 Quote from: dbannon on March 10, 2021, 07:54:59 amThanks getmem and lucamar.  I tried getmem's method, works perfectly.  But I must admit, I would never have dreamed of applying setlength() to a managed object like ANSIString !   (I went for getmem's method rather than add a new type to my binary) SetLength is the main means to preallocate any string type (or dynamic array). Of course one can always append elements (Wide)Char by (Wide)Char, but that is going to be slow due to reallocations. Better to preallocate the string (even if you don't know the exact size) and - if the exact size isn't known beforehand - then to either enlarge it further (factor 2 is usually used) or to shrink it accordingly if the end is reached. ---------------------------------------------------------------------- dbannon · 2021-03-10 10:56 Quote from: lucamar on March 10, 2021, 08:37:41 amYou were looking at the docs for old-style Objects instead of modern Classes Indeed I was.  I landed there from a google search, was not aware we had both objects and classes competing with each other in RTL ??  Both under 'current'.  The page I was on is labeled 'Base stream class' but says 'Objects' in top right corner.  Certainly explains why I could not make sense of at least one example I saw that used new()    If the object section of (some of) the RTL is deprecated, should there be something on the page that says "You probably don't want this page, try XXX" ?  @PascalDragon - that makes serious sense, I have code where I add to some strings char by char, I will now have to look to see if I can speed that up !  Thanks Davo ---------------------------------------------------------------------- PascalDragon · 2021-03-10 12:32 Quote from: dbannon on March 10, 2021, 11:56:18 amIf the object section of (some of) the RTL is deprecated, should there be something on the page that says "You probably don't want this page, try XXX" ? Objects are not deprecated. For example FreeVision, the text mode UI framework, is based on objects. ---------------------------------------------------------------------- lucamar · 2021-03-10 13:17 Perhaps a reading of the Reference Guide might help you understand better the differences: Objects vs. Classes. IIRC there is also some stuff about this in the wiki and, not much time ago, a rather lengthy discussion about them (and advanced records) in this forum. ---------------------------------------------------------------------- Warfley · 2021-03-10 15:41 About the original topic, I personally use the following class helper: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   TStreamHelper = class helper for TStream  public    function ReadRaw(const Count: Integer): String;    procedure ReadTo(const pattern: string; out Result: string; MaxLen: integer = 1024);    procedure WriteRaw(const Data: string);  end;With implementation: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i function TStreamHelper.ReadRaw(const Count: Integer): String;begin  if Count <= 0 then Exit;  SetLength(Result, Count);  ReadBuffer(Result[1], Count);end; {* ------------------------------------------------------- ---------------------- * Reads a stream until a pattern is found, maxlen is reached or an exception * is thrown. * On exception the result will still be a valid string. Can be used to read * until End of Stream * ---------------------------------------------------------- ------------------}procedure TStreamHelper.ReadTo(const pattern: string; out Result: string;  MaxLen: integer);var  c: char;  len: integer;  pLen: integer;  backtrack: integer;begin    if MaxLen <= 0 then Exit;  SetLength(Result, 128);  len := 0;  plen := 0;  backtrack := 0;  try    while len < MaxLen do    begin      c := char(Self.ReadByte);      Result[len + 1] := c;      Inc(len);      if len = Result.Length then        SetLength(Result, Result.Length * 2);      if pattern[pLen + 1] = c then      begin        if plen = 0 then      begin          backtrack := len;        end;        Inc(pLen);      if pLen = pattern.Length then          Exit;      end      else if plen > 0 then      begin        pLen := 0;        while backtrack + pLen < len do        begin          if pattern[pLen + 1] = Result[backtrack + pLen + 1] then            Inc(pLen)          else        begin            pLen := 0;            Inc(backtrack);        end;        end;      end;    end;  finally    SetLength(Result, len);  end;end; procedure TStreamHelper.WriteRaw(const Data: string);begin  if Data.Length = 0 then Exit;  self.WriteBuffer(Data[1], Data.Length);end; Example: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i stream := TMemoryStream.Create;try  stream.WriteRaw('Hello World');  stream.seek(0, soBeginning);  assert(stream.ReadRaw(stream.Length) = 'Hello World')finally  stream.Free;end;And readTo can for example be used to read C style (0 terminated) strings: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i stream := TMemoryStream.Create;try  stream.WriteRaw('Hello World'#0);  stream.seek(0, soBeginning);  stream.ReadTo(#0, output, Integer.MaxValue);finally  stream.Free;end; ---------------------------------------------------------------------- dbannon · 2021-03-11 02:30 Quote from: lucamar on March 10, 2021, 02:17:58 pmPerhaps a reading of the Reference Guide might help you understand better the differences: .... Oh, I understand the differences between Objects and Classes, its just that I landed on a page that listed methods and did not realize that it was an Object page, not a Class page. Top left it says 'class', top right it says 'object', I did not look at either, just looked at the list of methods ! My bad ... Davo ---------------------------------------------------------------------- dbannon · 2021-03-11 02:34 Thanks Warfley, quite a collection building here, might need to end up on the wiki ... Davo