Newsgroup: it.comp.lang.delphi
Titolo: Ma possibile che non si possa fare?!

Salve
Mettiamo il caso che volessi leggere tutto insieme da un file binario
(insomma che puo' contenere byte da 0..255) , n.byte chesso adesso facciamo
per esempio 3 mega e che questa quantita di dati che voglio leggere varia
ogni volta.
Poi voglio piazzare questi 3 mega di dati in una var per poi utilizzare la
funzione pos per vedere se e dove in questi dati c'e' una certa stringa, per
esempio 'ciao'.
Mettiamo poi che questi dati che voglio leggere non si trovano all'inizio
del file ma ho bisogno di usare il seek.
E per finire voglio riscrivere in un secondo file questi dati.
insomma:
apri file
seek qui;
leggi 3000000
ci sta' 'ciao' in questi 3 mega? bene a che punto?
scrivi nel file pippo i tre mega letti senza che mi incasini i dati.
Non riesco a farlo!!!!!!
E mi sto incazzando!!!
grazie.....scusate

 E mi sto incazzando!!!
Come puoi pretendere di infilare una serie di bytes (inclusi gli 0 [zero] )
in una stringa?
Puoi usare un array di char o, soluzione secondo me molto più decente, usa
un TFileStream e scorri il file cercando i bytes della stringa che ti
interessano...
Ciao
--
(¯`·.¸¸.·´¯`·.¸¸.-> Andrea <-.¸¸.·´¯`·.¸¸.·´¯)
AntiSpam: rimuovere il trattino basso dall'indirizzo per rispondere
AntiSpam: remove the underscore from the e-mail address to reply

 interessano...
Ma leggere byte x byte non risulta piu' lento?

 > Puoi usare un array di char o, soluzione secondo me molto piů decente,


 in una stringa?
Perché no?
var
  st : string;
begin
  st := 'Prova'#0'Il carattere precedente era chr(0).';
end;
Le stringhe del Delphi non sono come i char* del C, ci puoi anche metteri 
i caratteri nulli.
-- 
Roberto Lupi

 var CharBuffer : array[ 0..1023 ] of char;// Crea un buffer di 1kb
Ok...ma se la quantita' di dati varia ogni volta?
Non posso impostare un valore fisso.

Non posso impostare un valore fisso.
Se hai D4 utilizza gi array dinamici con la SetLength.
Ciao!
--
- Carlo -

> Se hai D4 utilizza gi array dinamici con la SetLength.
Anche se devo leggere 2 mega? fuziona o scoppia?

 wrote in message 8jofhn$ldo$1...@news.IT.net...


 i caratteri nulli.
E sai che ti dico? C'hai ragione: mi sono confuso, scusate... ;-)
Ciao,
--
Andrea Magni
E-Mail: 
ama...@energy.it
SMS: 
ama...@wappi.com
Ps: Treviglio (BG) : 30° ! (sigh)


E' vero, pero' bisogna fare cpmunque attenzione perche', per rendere
compatibile le AnsiString con i PChar, il Delphi aggiunge sempre in coda
alle stringhe lunche un #0, il quale carattere viene gestito in modo
particolare.
Non so se le "vecchie" funzioni (quali Pos e Copy per esempio) ignorino
questo fatto.
Ciao,
Stefano

 scrivi nel file pippo i tre mega letti senza che mi incasini i dati.
fs.Free;
fs := TFileStream.Create( 'pippo', fmCreate );
fs.WriteBuffer( pc, SizeOf( pc ));
poi dimmi se funziona.

 wrote in message
8jshhu$ft2$1...@pegasus.tiscalinet.it...

E usare direttamente un TMemoryStream? Non è più facile?
Ruggero

> E usare direttamente un TMemoryStream? Non è più facile?
Perchè più facile? Potresti fare un esempio?
Come fai a cercare una stringa e ottenere la posizione della prima
occorrenza di tale stringa, all'interno di un MemoryStream?

   fs.Read(pc^, fs.Size);
Voglio essere libero di leggere sia tutto il file o anche solo un pezzo
partendo dall'offset x
E questo e' come ho risolto:
Buffer : pchar;
Pezzo : String;
......
  SetLength(Pezzo, LunghezzaPezzo);
  buffer:=StrAlloc(LunghezzaPezzo);
  FileIn.Read(buffer^,LunghezzaBuffer);
  for i := 1 to LunghezzaBuffer do
  begin
  Pezzo[i] := Char(Pointer(Integer(buffer)+i)^);
  end;
 Posizione := pos(ParolaIn,Header);
Per leggere un mega e fare il pos ci mette + o - un secondo sul mio cesso di
computer.
Qualche sistema ancora piu' veloce?...postate il codice!!! :)))))
Saluti

 Qualche sistema ancora piu' veloce?...postate il codice!!! :)))))
Oh... dunque dunque dunque.... premesso che sono le 3 del mattino... e che
non ho testato questo
codice... :
const buflen = 1024*32-1;
         ParolaIn = 'Stringa da Cercare';
procedure TForm1.FormCreate(Sender: TObject);
var m : tmemorystream;
    n : integer;
    buffer : pchar;
    posizione : pchar;
begin
 m := tmemorystream.Create;
 m.loadfromfile ( 'nomefile' );
 getmem (buffer,buflen+1);
 Repeat
   n := m.Read ( buffer^, buflen );
   posizione := strpos (buffer, ParolaIn);
 Until ((n < buflen) or ( posizione <> nil ));
  N := (m.Position - buflen) + integer(posizione)-integer(buffer)
  m.free;
end;
Che te ne sembra ? Magari c'è da aggiustare qualcosa... magari no... magari
non va... sonno!!
Ciao! Fammi sapere se funziona!!  Davide DG

>
[Ruggero Rossi]


StrPos(PChar(Str2Find), PChar(MemStream.Memory));
cmq esiste anche la classe TStringStream che sembra fatta apposta;
**moolto** interessante anche l'esempio, che mi permetto di allegare
anche se OT
Saluti
Paolo Arosio
---------------------------------------------
"This example shows how to use the built-in VCL component streaming
support to convert any component into a string and convert that string
back into a component.
function ComponentToString(Component: TComponent): string;
var
  BinStream:TMemoryStream;
  StrStream: TStringStream;
  s: string;
begin
  BinStream := TMemoryStream.Create;
  try
    StrStream := TStringStream.Create(s);
    try
      BinStream.WriteComponent(Component);
      BinStream.Seek(0, soFromBeginning);
      ObjectBinaryToText(BinStream, StrStream);
      StrStream.Seek(0, soFromBeginning);
      Result:= StrStream.DataString;
    finally
      StrStream.Free;
    end;
  finally
    BinStream.Free
  end;
end;
function StringToComponent(Value: string): TComponent;
var
  StrStream:TStringStream;
  BinStream: TMemoryStream;
begin
  StrStream := TStringStream.Create(Value);
  try
    BinStream := TMemoryStream.Create;
    try
      ObjectTextToBinary(StrStream, BinStream);
      BinStream.Seek(0, soFromBeginning);
      Result := BinStream.ReadComponent(nil);
    finally
      BinStream.Free;
    end;
  finally
    StrStream.Free;
  end;
end;

>
E questo e' come ho risolto:
Buffer : pchar;
Pezzo : String;
......
  SetLength(Pezzo, LunghezzaPezzo);
  buffer:=StrAlloc(LunghezzaPezzo);
  FileIn.Read(buffer^,LunghezzaBuffer);
  for i := 1 to LunghezzaBuffer do
  begin
  Pezzo[i] := Char(Pointer(Integer(buffer)+i)^);
  end;
 Posizione := pos(ParolaIn,Header);
Per leggere un mega e fare il pos ci mette + o - un secondo sul mio
cesso di
computer.
Qualche sistema ancora piu' veloce?...postate il codice!!! :)))))
<<
Ci sono alcune considerazioni da fare: se leggi il file a pezzi è
possibile che la stringa (se c'è), ti venga restituita in due pezzi
diversi, cosa che impedirebbe di trovarla. D'altra parte, se il file è
_grosso_ caricarlo in memoria può essere improponibile.
La seguente funzione è stata provata per cercare una stringa in uno dei
file dbx dove OE lascia i messaggi scaricati dai NG. La dimensione del
file era di ~7.6M. Non è granchè performante (~600 ms per la prima
ricerca su un P200, 192M, NT4)
NB: ovviamente può andare solo per una singola ricerca, altrimenti è
demenziale.
hth
Paolo Arosio
------------------------------------------------------
{.$DEFINE Timing}
{$IFDEF Timing}
const
  StartTick: Cardinal = 0;
  StopTick: Cardinal = 0;
{$ENDIF}
function FindStringInFile(const Str2Find, fn: String; const FromIdx:
Cardinal; var Idx: Cardinal): boolean;
var
  ss: TStringStream;
  ms: TMemoryStream;
  ssLen: cardinal;
begin
  {$IFDEF Timing}
  StartTick := GetTickCount();
  {$ENDIF}
  Result := false;
  Idx := 0;
  if not FileExists(fn) then
    Exit;
  ms := TMemoryStream.Create;
  try
    ms.LoadFromFile(fn);
    if FromIdx > 0 then begin
      if FromIdx >= ms.Size then
        raise Exception.Create('File isn''t that long');
      ms.Seek(FromIdx, soFromBeginning);
    end
    else
      ms.Seek(0, soFromBeginning);
    ss := TStringStream.Create('');
    try
      if FromIdx = 0 then
        ssLen := ss.CopyFrom(ms, 0)  // copies entire source
      else
        ssLen := ss.CopyFrom(ms, ms.Size - fromIdx);
      if ssLen <> (ms.Size - fromIdx) then
        Raise Exception.Create('Problem in reading string');
      Idx := Pos(Str2Find, ss.DataString) + FromIdx;
      Result := Idx <> FromIdx;
    finally
      ss.Free;
    end;
  finally
    ms.Free;
  end;
  {$IFDEF TIMING}
  StopTick := GetTickCount();
  {$ENDIF}
end;


Non so se guadagni qualcosa in velocita', ma un problema del genere sarebbe
risolvibile elegantemente con i file mappati in memoria di Win32
Ciao,
Stefano

>[...] leggere tutto insieme da un file binario
(insomma che puo' contenere byte da 0..255) , n.byte chesso adesso
facciamo
per esempio 3 mega e che questa quantita di dati che voglio leggere
varia
ogni volta.
Poi voglio piazzare questi 3 mega di dati in una var per poi utilizzare
la
funzione pos per vedere se e dove in questi dati c'e' una certa stringa,
per
esempio 'ciao'.
<<
vedi anche l'articolo su
http://community.borland.com/article/0,1410,22411,00.html
che cerca stringhe di testo in file(s) all'interno di thread e con
notifica alla form principale.
hth
Paolo Arosio

GRAZIE A TUTTI!!!!