Newsgroup: it.comp.lang.delphi
Titolo: TMemoryStream e String

Devo chiedere perchè non ne vengo fuori. Google, help,esempi...non ho
trovato!
Devo inviare una serie di stringhe da un TIdTCPServer ad un TIdTCPClient in
un blocco solo e non mi impensieriva fino a che non mi sono trovato a
farlo...niente da fare. Forse mi intestardisco con il WriteStream mentre
Indy mette a disposizione anche degli altri metodi.
Ma non capisco perchè caricando il buffer con dei numeri e leggendoli con
While DataStream.Read(N, SizeOf(N)) > 0 ogni N rappresenta un singolo numero
mentre al contrario con le stringhe tutto quello che sono riuscito a fare è
ottenerne una unica.
Potrei ovviare caricandole con un carattere separatore ed estrarle poi con
ExtractStrings ma vorrei chiarire questa cosa.
Vi posto il codice:
Lato server:
SRVStream := TMemoryStream.Create;
SRVStream.WriteBuffer('prima', length('prima'));
SRVStream.WriteBuffer('seconda', length('seconda'));
DataSize := SRVStream.Size;
AThread.Connection.WriteCardinal(DataSize);
AThread.Connection.WriteStream(SRVStream);
SRVStream.Free;
Lato client
CLIStream := TMemoryStream.Create;
DataSize := CLI.ReadCardinal;
if DataSize > 0 then
begin
  CLI.ReadStream(CLIStream, DataSize);
  CLIStream.Position := 0;
  // e ora sia che utilizzi un Memo1.Lines.LoadFromStream(CLIStream)
  // oppure
  // carico lo stream in una TStringList
  // ottengo sempre la stringa 'primaseconda'
end;
Questo forse vuol dire che l'errore sta nel preparare lo stream da inviare.
Riuscite a darmi una direzione?
Valter

 Indy mette a disposizione anche degli altri metodi.
[...]
Forse ho trovato:
lato server:
var
  STsrv: TStrings;
STsrv := TStringList.Create;
STsrv.Clear;
STsrv.Add('prima');
STsrv.Add('seconda');
NumStrSrv := STsrv.Count;
AThread.Connection.WriteCardinal(NumStrSrv);
AThread.Connection.WriteStrings(STsrv);
lato client:
var
  STcli: TStrings;
NumStrCli := CLI.ReadCardinal;
if NumStrCli > 0 then
begin
  STcli := TStringList.Create;
  STcli.Clear;
  CLI.ReadStrings(STcli, NumStrCli);
  for i := 1 to STcli.Count do
    Memo1.Lines.Add(STcli.Strings[i-1];
end;
Così facendo ottengo tutte le stringhe individualmente, insomma invio e
leggo una TStringList.
Avrei però bisogno di due chiarimenti, se qualcuno me li può fornire:
ho visto che usando AThread.Connection.WriteRFCStrings il risultato è lo
stesso.
Quando andrebbe usato?
Ma quello che mi è rimasto qui  :-)
con il WriteStream non è proprio possibile inviare un blocco di stringhe e
leggerle poi individualmente senza usare ExtractStrings?
Grazie e ciao a tutti.
Valter

 leggerle poi individualmente senza usare ExtractStrings?
E' possibile inviare qualunque cosa una di seguito all'altra purche' siano 
precedute dalle loro dimensioni: se ci metti piu' stringhe, es.
s1:='prova';
n:=Length(s1)
MemStream.Write(n,4); // n e' un Integer da 4 byte
MemStream.Write(s1[1],n);
s2:='Seconda';
n:=length(s2);
MemStream.Write(n,4); // n e' un Integer da 4 byte
MemStream.Write(s2[1],n);
...
Analogamente in ricezione leggerai in n i primi quattro byte, poi la prima 
stringa,ecc.
Giorgio 

 stringa,ecc.
[..]
Grazie per la risposta Giorgio, ma continuo ad essere in difficoltà...mi sa 
che questo TStream è per me un pò com'era la geografia a scuola...quando non 
ti va giù fai grande fatica!
Ho predisposto una form di prova con un client ed un server Indy 9.
Mi connetto, invio un Command ed il server risponde:
creo un TMemoryStream
ci infilo dimensione e rispettiva stringa
altra dimensione e rispettiva stringa
invio con un writecardinal il size dello stream
invio lo stream
il client:
riceve il cardinal
legge lo stream
riavvolgo lo stream
leggo la prima dimensione contenuta nello stream: corretta
ora buio...come leggo la stringa successiva alla dimensione?
Sono convinto che la domanda è banale ma...non mi entra
Ciao
V

 ora buio...come leggo la stringa successiva alla dimensione?
n: Integer; s1,s2: String;
Stream.Position:=0;
Stream.Read(n,4);
SetLength(s1,n); // Prepari la dimensione della stringa al n. di caratteri 
che ricevera'
Stream.Read(s1[1],n);
Stream.Read(n,4);
Setlength(s2,n);
Stream.Read(s2[1],n);
ecc.
Ciao Giorgio

 SetLength(s1,n); // Prepari la dimensione della stringa al n. di caratteri
[..]
ecco dove si era nascosto, ccidenti!  :-)
Ancora un pò e non ci dormivo...
Grazie davvero
Ciao
V