0

Already I had a problem with sending data using the TIdHTTP component in Delphi 11, and I got the solution from Getting spaces after upgrading from Indy 9 on Delphi 6 to Indy 10 on Delphi 11.

// sUrl - DSOAP Url
// streamRequest - Request Stream and it will send as compressed data.
// streamResponse - TStream of the response of DSOAP and it will receive as compressed.
IdHttp.Post(sUrl, streamRequest, streamResponse)

Now, I'm facing the problem after receiving the data. How can I read the data from the stream using Delphi 11?

Here is the code to convert the received stream to a string. After calling this method, I'm getting some junk value:

var 
  xml: PChar;
  sXML: string;
  iLength: string;
  streamResponse: TStream; // Before this method, the response is decompressed using ZLib decompression Logic
begin
  iLength := streamResponse.Seek(0, 2);
  xml = strAlloc(iLength+1);
  FillChar(xml^, iLength+1, #0);
  streamResponse.Seek(0, 0);
  streamResponse.Read(xml^, iLength);
  sXML := strPas( xml );   // Getting error after calling this.
  strDispose(xml);
end;

This logic works fine in Delphi 6, but is getting an error while using Delphi 11.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
sn_na_v
  • 31
  • 5
  • 1
    I would bet your problem is because of the change of the string type from ANSI to Unicode between D6 and D11, not the change from 32 to 64 bits compilation! – Delphi Coder Jul 26 '23 at 12:35
  • IMHO use `stream.Position` instead of `stream.Seek` – complete_stranger Jul 26 '23 at 12:42
  • In Delphi 6 all string is AnsiString that's meens that every char is 1-byte. In Delphi 11 default codeing is 2-byte string, thats why your code does not working in same way. As i saw in your previous solution you decode string in UTF-8 that's means that Char got variable size from 1 to 4 bytes that's why you can't just do `streamResponse.Read(xml^, iLength * sizeOf(char));` and you need to use TEncoding to convert bytes into string. – Oleksandr Morozevych Jul 26 '23 at 13:50
  • 1
    @sn_na_v You didn't need to delete your [previous question](https://stackoverflow.com/questions/76765758/) just to re-ask the same question with more detail. You can edit your questions. I will repost the relevant portion of my previous comment that still applies here: "*Just as you had to make your sending code account for the migration from ANSI to Unicode, ... you likely need to account for that in your receiving code, too.*" – Remy Lebeau Jul 26 '23 at 16:23
  • 1
    @sn_na_v Why not simply let `TIdHTTP` handle both the decompression and the conversion to `string` for you in one go? If the response is compressed, you can assign a `Compressor` to `TIdHTTP` to decompress it. And you can use an overload of `TIdHTTP.Post()` that returns a `string` instead of fills a `TStream` – Remy Lebeau Jul 26 '23 at 16:29

1 Answers1

1

First of all - you must to check if you decompress stream in a right way.

You can do in by saving content of stream in file and open it by any text editor.

streamResponse.SaveToFile('c:\temp\MyStream.txt');

If all is fine - convert it into string:

var
  sStream : TStringStream;
  sXML : string;
...      
  sStream := TStringStream.Create('', TEncoding.UTF8);
  try
    sStream.LoadFromStream(streamResponse);
    sXML := sStream.DataString;
  finally
    sStream.Free
  end;
end;
  • FYI, since he's already using Indy, there is a `ReadStringFromStream()` function in the `IdGlobal` unit which takes an `AByteEncoding` parameter, eg: `sXML := ReadStringFromStream(streamResponse, -1, IndyTextEncoding_UTF8);` – Remy Lebeau Jul 26 '23 at 16:26
  • Thanks a Lot , the above answer works perfectly. – sn_na_v Jul 27 '23 at 10:38