Reading n-Bytes from TCP - How to convert AnsiStr to Bytes and vice versa? lazarus / 38-Networking and Web Programming ---------------------------------------------------------------------- FrankBKK · 2021-05-25 17:35 Hope somebody can help me with this problem - I have to read data from an interface that is specified like this: Using TDataPortTCP I can read the buffer with Dataport.Peek(size) and pull the data from the buffer with Dataport.Pull(size) - both methods provide the result as AnsiStr, the data itself (except for the length- info) is in plain ASCII, each line terminated by #10 I imagine that something like this should work, but I have no idea how to convert AnsiStr to Bytes and vice versa: 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    while DataPortTCP.Peek(2) > ZeroBytes do   begin      LengthInBytes := DataPortTCP.Pull(2) ;      sContent := DataPortTCP.Pull(LengthInByte) ;      // do something with sContent   end; How do I declare / get / convert the pseudo-vars ZeroBytes and LengthInBytes and how do I have to deal with Endianess ? Unfortunately I know nothing about TBytes etc. and what I read so far did only lead to more confusion ;-) I would be very grateful if someone could point me into the right direction. ---------------------------------------------------------------------- engkin · 2021-05-25 19:14 To change the endianness use BEToN or LEToN. To turn a string into an array of bytes, use BytesOf from unit SysUtils. This would be more like: 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 uses...  SysUtils;...var  LengthInBytes:Word;//<--Two bytes;  sContent:AnsiString;  Bytes: TBytes;begin  ..  while DataPortTCP.Peek(2) > ZeroBytes do  begin     LengthInBytes := DataPortTCP.Pull(2) ;     sContent := DataPortTCP.Pull(LengthInByte) ;     // do something with sContent     LengthInBytes:=BEToN(LengthInBytes);     Bytes:=BytesOf(sContent);...  end; TBytes is an array of byte: The first value is Bytes[0], the second one is Bytes[1], ...etc You can access the ASCII chars instead: The first char is sContent[1], the second one is sContent[2], ...etc ---------------------------------------------------------------------- FrankBKK · 2021-05-26 05:48 Thanks for your feedback, that helped me understand the issue better ! 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 LengthInBytes := DataPortTCP.Pull(2) ;  unfortunately this does not work as Pull returns an AnsiString whereas LengthInBytes is Word I still need help in figuring out - how to convert this string into bytes that show the proper length - then convert that back into an integer so I can pull the next batch of data with DataPortTCP.Pull(length). Let me try to explain: DataPortTCP.Pull(n) takes characters / bytes out of the buffer and returns them as AnsiString. DataPortTCP.Pull() takes ALL chars out of the buffer. The messages I receive have the format    LengthOfMessage + Message   where LengthOfMessage are two bytes, Message are in ASCII127  e.g. <#00#06a text> The end of all messages sent is defined as a message with values  <#0#0> I can read the whole buffer in one shoot by ignoring the #0's and extract anything > #31 - unfortunately that gives me some garbage when the message is longer than 31 chars as the two bytes at the begin of each msg that contain the msg length then display as standard ASCII e.g. <#00#65a very long text with sixty five chars here ....> which converts to So the only way to get ungarbled msgs is to read the two bytes length n, convert that to an integer then  get the next n chars and repeat until #0#0 is received And that's where I got lost -  I have no idea how I can extract and convert the length of the line as a proper value ---------------------------------------------------------------------- dseligo · 2021-05-26 05:59 Try something like 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 strLengthInBytes:String;    sContent:String;    LengthInBytes:Integer;...       while DataPortTCP.Peek(2) > ZeroBytes do       begin          strLengthInBytes := DataPortTCP.Pull(2) ;        // I don't know if you need to check if you actually received two characters or are you          // sure that you will always have two characters here          LengthInBytes := Ord(strLengthInBytes[1])*256+Ord(strLengthInBytes[2]);          sContent := DataPortTCP.Pull(LengthInBytes);          // do something with sContent       end; ---------------------------------------------------------------------- FrankBKK · 2021-05-26 16:01 Thanks everybody for all your valuable input and suggestions - I learned a lot ! While playing around with all the suggested solutions I came up with another way that seems to be considerable faster and avoids all those pesky issues with Byte / String conversions: 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   i : LongInt ;   iBegin, iLength : Integer ;   sLine, sTimeStamp, sEvent : String ;   gsRawEvents : AnsiString ;begin   // get all messages in one shot   gsRawEvents := gsRawEvents + DataPortTCP.Pull() ;    // start extracting from the first char after the 2-byte length-info   iBegin := cByteLen + 1 ;    // go through the whole string, char by char   for i := 1 to Length(gsRawEvents) do   begin      // we found a linefeed -> a msg ends here      if gsRawEvents[i] = #10 then      begin         // we extract that line         iLength := i - iBegin ;         sLine := sm.Copy(gsRawEvents,iBegin,iLength) ;          // separate Timestamp and Event-Text         sTimeStamp := sm.Copy(sLine, 1, cTsLength ) ;         sEvent     := sm.Copy(sLine, cTsLength + cTsBlank ) ;          // set the begin of the next msg line - we ignore the first two chars         // as they contain only the length of the next msg as byte values         // which contain control codes - we don't want them in our text         iBegin := i + cByteLen + 1 ;      end;   end;end; ---------------------------------------------------------------------- engkin · 2021-05-27 01:32 For the future if needed something similar. Here is how to do it using absolute: 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  LengthInStr:ShortString;  LengthInBytes:Word absolute LengthInStr[1];begin...    LengthInStr:=DataPortTCP.Pull(2);    LengthInBytes:=BEtoN(LengthInBytes);... LengthInBytes would occupy the same first two bytes of LengthInStr.