[Last Call] Learn about multicloud storage options and how to improve your company's cloud strategy. Register Now

x
?
Solved

Stream to pascal string conversion

Posted on 2000-02-27
16
Medium Priority
?
644 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
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
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 200 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

Enroll in October's Free Course of the Month

Do you work with and analyze data? Enroll in October's Course of the Month for 7+ hours of SQL training, allowing you to quickly and efficiently store or retrieve data. It's free for Premium Members, Team Accounts, and Qualified Experts!

Question has a verified solution.

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

Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
In response to a need for security and privacy, and to continue fostering an environment members can turn to for support, solutions, and education, Experts Exchange has created anonymous question capabilities. This new feature is available to our Pr…
We’ve all felt that sense of false security before—locking down external access to a database or component and feeling like we’ve done all we need to do to secure company data. But that feeling is fleeting. Attacks these days can happen in many w…
Suggested Courses

656 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