Solved

Stream to pascal string conversion

Posted on 2000-02-27
16
618 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
  • 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
Windows Server 2016: All you need to know

Learn about Hyper-V features that increase functionality and usability of Microsoft Windows Server 2016. Also, throughout this eBook, you’ll find some basic PowerShell examples that will help you leverage the scripts in your environments!

 
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

Problems using Powershell and Active Directory?

Managing Active Directory does not always have to be complicated.  If you are spending more time trying instead of doing, then it's time to look at something else. For nearly 20 years, AD admins around the world have used one tool for day-to-day AD management: Hyena. Discover why

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
How to convert wav to mp3 in delphi 9 202
code issue 8 132
Intraweb download file link ? 1 135
Why is there a Difference between the SQL String and using the Parameter ? 7 38
In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
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…
In a recent question (https://www.experts-exchange.com/questions/28997919/Pagination-in-Adobe-Acrobat.html) here at Experts Exchange, a member asked how to add page numbers to a PDF file using Adobe Acrobat XI Pro. This short video Micro Tutorial sh…
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…

821 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