Solved

Stream to pascal string conversion

Posted on 2000-02-27
16
627 Views
Last Modified: 2010-04-04
I need a conversion from TStream to "string", BUT:
- it has to support #0 's in the stream, and thus in the string
- at the end, the string length must be correct.
- it should be lightning fast and efficient.

The best I could make up:

for myInt := 0 to Stream.Size do
begin
   Stream.Read(myChar,1)
   Result := Result + myChar;
end;

But as you can see it uses a loop which fills a (dynamic growing) string. I'd like something more like allocate a string or memorypart, do a single conversion (some typecast or whatever) and put it in result. But I don't know how...

Any Ideas?
0
Comment
Question by:leon321
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 4
  • 4
  • +2
16 Comments
 
LVL 10

Expert Comment

by:ptmcomp
ID: 2562703
What's about this:

var
  s: String;
begin
  SetLength(s, Stream.Size);
  Sream.Position:=0;
  Stream.Read(PChar(s[1]), Stream.Size);
end;
(Not tested, but should work...)
ptm.
0
 

Author Comment

by:leon321
ID: 2562704
Off course I meant,
for myInt := 0 to (Stream.Size-1) do

Leon.
0
 
LVL 7

Expert Comment

by:ahalya
ID: 2562747
I use this to read a TMemoField into a string:

function TSearchForm.GetBlobAsString(Blob:TBlobField): string;

var
   BlobStream: TBlobStream;
   a: array [0..1024] of Char;
   i:longint;

begin
Result:='';
BlobStream := TBlobStream.Create(Blob, bmRead);
   try
   i := BlobStream.Size;
   FillChar(a, i, #0);
   FillChar(a, SizeOf(a), #0);
   BlobStream.Read(a, i);
   finally
   BlobStream.Free;
  end;
a[i] := #0; {set the last character as null}
Result:=StrPas(a);
end;
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 10

Expert Comment

by:ptmcomp
ID: 2562776
What's about this:

var
  s: String;
begin
  SetLength(s, Stream.Size);
  Sream.Position:=0;
  Stream.Read(PChar(s[1]), Stream.Size);
end;
(Not tested, but should work...)
ptm.
0
 

Author Comment

by:leon321
ID: 2562954
ptmcomp: you are using a explicit pchar typecast.
ahalya: you are using an implicit pchar typecast. (StrPas expects an pchar parameter)

Both cases, my value would be truncated at the first #0 occurence. This is exactly what I do not want.

If my stream would contain: 'something'#0'otherdata'
My pascal string would have to contain also the exact same data. (and not be truncated to 'something')

Regards,
Leon.










0
 
LVL 7

Expert Comment

by:ahalya
ID: 2563051
How about this ?  (btw, if i use long string and SetLength(s, i) then it raises an exception, but if you can live with a short string then this shd be ok)


  var
   BlobStream: TBlobStream;
   a: array [0..255] of Char;
    i:longint;
    s : shortstring;

 begin
 BlobStream := TBlobStream.Create(Blob, bmRead);
  i := BlobStream.Size;
  i := BlobStream.Read(a, i);
  BlobStream.Free;

  copyMemory(@s[1], @c, i);
  s[0] := chr(i);
  end;

0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 2563913
hi all,

what about this?

procedure TForm1.Button1Click(Sender: TObject);
var
  F : TMemoryStream;
  s : String;
begin
  F := TMemoryStream.Create;
  Try
    F.LoadFromFile('u:\zerostr.txt');
    SetString(s,PChar(F.Memory),F.Size);

    //Prepare for OutPut (windowControls don't like #0 chars in a string
    while pos(#0,s) <> 0 do s[pos(#0,s)] := #1;
    ShowMessage(s);
  finally
    F.Free;
  end;
end;

meikl
0
 

Expert Comment

by:aacrg
ID: 2564657
To Leon321
Sorry, but you're wrong about the typecasting Stream.Read(PChar(s[1]), Stream.Size) means the same as Stream.Read(@s[1], Stream.Size). The PChar is just refering the beginning of the memory where the data has to be stored.

0
 

Author Comment

by:leon321
ID: 2570368
ptmcomp: you're first example I cannot compile: constant object cannot be passed as var parameter


ahalya : you're first example requires a buffer (you declared as 1024) bytes, but I need something dynamic. Since the stream could be 200k as well.

kretzschmar : I'm affraid the Memory property you're using, is only available in TMemoryStream, TStream does not have such property..

Regards,
Leon
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 2570511
to leon

you've never said which kind of stream you use
and nevertheless you can use
TMemoryStream.LoadFromStream(YourStream);
to get it into a TMemorystream

meikl
0
 
LVL 10

Accepted Solution

by:
ptmcomp earned 50 total points
ID: 2570794
Sorry, this one I could compile:

var
  s: String;
  Stream: TStream;
begin
  SetLength(s, Stream.Size);
  Stream.Position:=0;
  Stream.Read(s[1], Stream.Size);
end;

Regards, ptm. >;0)
0
 

Author Comment

by:leon321
ID: 2571760
I'm sorry Meikl, but the first line of my question contains "TStream to "string" ". So I meant all TStream descendants, not only TMemoryStream :(

ptmcomp, I'll try you're new example today!

Leon.
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 2571805
well leon,

what about this ?

function StreamToString(Stream : TStream) : String;
var ms : TMemoryStream;
begin
  Result := '';
  ms := TMemoryStream.Create;
  try
    ms.LoadFromStream(Stream);
    SetString(Result,ms.memory,ms.Size);
  finally
    ms.free;
  end;
end;

meikl
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 2571818
one correction

function StreamToString(Stream : TStream) : String;
var ms : TMemoryStream;
begin
  Result := '';
  ms := TMemoryStream.Create;
  try
    ms.LoadFromStream(Stream);
    SetString(Result,PChar(ms.memory),ms.Size);
  finally
    ms.free;
  end;
end;

//sample to call

procedure TForm1.Button2Click(Sender: TObject);
var
  fs : TFileStream;
  s : String;
begin
  Fs := TFileStream.Create('u:\zerostr.txt',fmOpenRead);
  Try
    s := StreamToString(fs);

    //Prepare for OutPut (windowControls don't like #0 chars in a string
    while pos(#0,s) <> 0 do s[pos(#0,s)] := #1;
    ShowMessage(s);
  finally
    Fs.Free;
  end;
end;

meikl
0
 

Author Comment

by:leon321
ID: 2573878
ptmcomp it works! Since you're the first, you'll get the points. The index on s[1] is the essential trick here, I tried something similar a few days ago without that index and it only gave access violations. (may be the compiler is not smart enough and references s[0] in that case..)

Either way, thanks all!

0
 
LVL 10

Expert Comment

by:ptmcomp
ID: 2574370
Fine. I think it would also work with Stream.Read(Pchar(s)^, Stream.Size) - all what you need is a dereferenced pointer to the beginning of the memory where to put the data.
0

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Working with hours 3 74
Error E2158 compiling with Delphi XE10 Seattle 2 127
Twebbrowser add css to the header 3 39
MS Access from Delphi 31 81
This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
In an interesting question (https://www.experts-exchange.com/questions/29008360/) here at Experts Exchange, a member asked how to split a single image into multiple images. The primary usage for this is to place many photographs on a flatbed scanner…
Are you ready to implement Active Directory best practices without reading 300+ pages? You're in luck. In this webinar hosted by Skyport Systems, you gain insight into Microsoft's latest comprehensive guide, with tips on the best and easiest way…

726 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question