Newsgroup: it.comp.lang.delphi
Titolo: 53 byte alla volta

Come faccio a leggere un file di testo 53 byte alla volta?
Lo so, è banale (per voi)...

> Come faccio a leggere un file di testo 53 byte alla volta?
Utilizzando un po' di funzioni rudimentali sono giunto a questo, non escludo
che ci siano funzioni più nuove che permettano di ottenere lo stesso
risultato in maniera più efficiente:
procedure TForm1.Button1Click(Sender: TObject);
var
  MioFile : File of Char;
  Dim, Rip, I, J : Integer;
  Lista : TStringList;
  Stringa : String;
  Lettera:Char;
begin
   Lista := TStringList.Create;
   AssignFile(MioFile,'c:\prova.txt');
   Reset(MioFile);
   Dim := Filesize(MioFile);
   Rip := Dim div 53;
   For I := 1 to Rip do begin
      Stringa := '';
      For J := 1 to 53 do begin
          Read(MioFile,lettera);
          Insert(lettera,Stringa,Length(Stringa));
      end;
      Lista.Add(Stringa);
   end;
end;
Dovrebbe funzionare, cmq attento che se il file i caratteri non sono
multipli di 53 (byte) alla fine avanzano dei caratteri ... per considerare
anche quelli ti posizioni (con Seek) alla posizione Dim - (Dim mod 53) e li
scorri fino ad EOF. Nota che i valori sono memorizzate in un oggetto
TStringList che va poi liberato dalla memoria.
Ciao!
--
- Carlo -
c.b...@libero.it

 Lo so, è banale (per voi)...
TMemoryStream penso faccia al caso tuo, prova guarda sull'help
eventualemente riscrivi
dovrebbe essere qualcosa del genre:
MemoryStream.Read(Buffer, NumeroByte)
Ciao,
Alan Solo

 MemoryStream.Read(Buffer, NumeroByte)
E io che mi sono scritto tutta la funzione! :(
Ciao! :)


 ha scritto nel messaggio
news:JBAT5.34417$FV2.1...@news.infostrada.it...


 end;
Quanto hai scritto legge una sequenza di 23 byte (la richiesta era di 53, ma
non è qui il punto), si richiedeva di leggere un intero file a gruppi di
Byte ... sicuramente la FileRead è migliore del Read, perchè io con il Read
devo fare 53 cicli da 1 byte e tu uno da 53 byte, cmq resta il fatto che
quel codice non fa quanto richiesto, dovresti controllare un po' di cose per
sapere la dimensione del file etc..
Ciao!





 (come ad esempio da memoria)
 
TMemoryStrea e' una classe, che come tutte le altre vcl ti offre molte
comodita' RAD, adesso al volo non me le ricordo tutte, ma ad es. puoi
leggere n byte dalla fine/dall'inizio/dalla posizione corrente/...
hai i classici metodi LoadFromFile/Stream e SaveTo..., ecc...
ps: visto che siamo in argoemnto di puntualizzazioni, la var h sarebbe meglio
dichiararla come THandle 
Ciao,
Alan Solo

 oppure mi sfugge qualcosa.
Evidentemente mi sono espresso male: il tuo codice legge sì la sequenza di
caratteri prefissata, ma si ferma la!
Supponi di avere un file formato da 106 caratteri, la tua funzione legge i
primi 53(23) e poi termina, ma questa non è la richiesta: "Come faccio a
leggere un file di testo 53 byte alla volta?" è ben diverso da "Come faccio
a leggere 53 byte da un file di testo?". Capito cosa intendo dire? Quella
FileRead va eseguita N volte, dove N è NumeroCaratteri / 53 ... a quel punto
leggi tutti i byte a gruppi di 53, se poi alla fine dovessero avanzare dei
Byte (perchè il numero di caratteri non è multiplo di 53), questo numero di
caratteri sarebbe il resto di NumeroCaratteri diviso 53. Se ti può aiutare a
capire riscrivo la funzione di lettura di un file di testo 53 Byte x volta
mediante le funzioni da te utilizzate.
Ciao!



Ciao

 dura.
scusami, anch'io ho letto male, tu leggi *solo* i primi 23 byte,
il ciclo e' proprio quello che ti e' sfuggito (anche me ;))
Ciao,
Alan Solo

 Se non e' questo vuol dire che ho la testa abbastanza dura.
Si, a grandi linee è quel che manca ... ora riscrivo l'intera procedura
corretta:
Procedure SomeBytes ( FileName : ShortString;
                                    ByteNumber : Integer;
                                    Lista : TStringList );
Var FH  : THandle;
       Dim, N, Counter : Integer;
       TempBuffer : Array [1..53] of Char;
begin
  FH  := FileOpen(FileName,fmOpenRead);
  Dim := FileSeek(FH,0,2);
  FileSeek(FH,0,0);
  N := Dim div ByteNumber;
  For Counter := 0 to N - 1 do begin
    FileRead(FH, TempBuffer , ByteNumber);
    Lista.Insert(Counter,String(TempBuffer));
  end;
end;
Così seleziona il numero di Byte passati e ignora i byte "residui" oltre
l'ultimo multiplo di 53 ...
Ciao!



Scusate se aggiungo ancora qualcosa di forse inutile per gli scopi di
Kata32.
Suggerirei di aggiungere un blocco try..finally per la gestione di
possibili eccezioni ed un minimo di verifica sul fatto che l'handle
ritornato da FileOpen sia valido.
Inoltre, quando si passa un buffer e la sua dimensione ad una funzione
che deve scrivere sul buffer, e' considerato buona norma utilizzare
sizeof.
Infine, il ciclo potrebbe essere terminato quando FileRead ritorna un
numero di byte diverso da quello richiesto.
Saluti
Paolo Arosio

 numero di byte diverso da quello richiesto.
Questo punto non lo ho capito. Perchè FileRead dovrebbe tornare un numero di
Byte diverso da quello richiesto?
Ciao e grazie per eventuali illustrazioni.


 Byte diverso da quello richiesto?
Dal help su FileRead :
FileRead reads Count bytes from the file specified by Handle into the
buffer. The Count parameter indicates the size, in bytes, of the buffer. The
function result is the actual number of bytes read, which may be less than
Count.
Quindi se leggi un file di 153 byte a blocchi da 50 byte, ti ritorna 50, 50,
50, 3
(se il file è da 150 ti ritorna 50,50,50,0)
Funziona praticamente come il parametro Result della BlockRead
A proposito... ma perchè non usate la blockread e le funzioni "standard"
consigliate da Delphi ?
Ciao, Davide DG

 consigliate da Delphi ?
non ho mai usato la blockread, ecco un mio codice alternativo
(con tMemoryStream)
procedure LeggiFile(NF: string; N: integer; L: TStringsList);
var F: TMemoryStream;
    Buffer: array [1..100] of char;
begin
 try
  F:=TMemoryStream.Create;
  F.LoadFromFile(NF);
  while F.Read(Buffer, N)=N
   do L.Add( string(Buffer) );
 finally
  F.Free;
 end;
end;
Ciao,
Alan Solo

 consigliate da Delphi ?
Io avevo utilizzato le funzioni superbasilari, con la Read, mi è stato detto
di utilizzare FileRead e ho riscritto l'esempio ... ti prego non mi fare
riscrivere l'esempio con Blockread! :)
Scherzi a parte, io sono tutt'altro che esperto nella gestione dei File
(faccio quel che mi serve e non vado oltre, non mi piace molto lavorare con
i file), sinceramente era la prima volta che utilizzavo
FileOpen/FileRead/FileSeek/FileClose etc... cmq darò un'occhiata a questa
Blockread!


     Buffer: array [1..100] of char;
Alan, ho notato che anche io ho commesso lo stesso errore, entrambi
dichiariamo un array di dimensioni fisse ma non controlliamo che il numero
di Byte richiesti sia minore di quello possibile ... dovremmo utilizzare la
SetLength con un bell'array dinamico.


 utilizzare la SetLength con un bell'array dinamico.
giusto.
...o, meno elegantemente, fare
if N > SizeOf(Array) then (Exit e qualcosa del genere)
...e' questo che intendevi, Paolo?
oppure ti riferivi a Read(Buffer, SizeOf(Buffer))?
Ciao,
Alan Solo

ho mai utilizzato il SizeOf.
Maggior documentazione non saprei (l'help di D. dice solo "SizeOf is
useful for determining the amount of memory to specify for the FillChar,
Move, or GetMem procedures.")
Si usa soprattutto sui tipi, ma e' utile anche con vettori e simili (per
stringhe ovviamente si usera' Length).
btw, nella funzione ricevevi il numero di caratteri da leggere come
parametro, ma dichiaravi il buffer staticamente.
A dire la verita', se non uso le classi della VCL o le funzioni Pascal,
preferisco usare direttamente le Api che i wrapper di Delphi per
l'accesso ai file.
Saluti
Paolo Arosio

oppure ti riferivi a Read(Buffer, SizeOf(Buffer))?
Nel mio messaggio suggerivo di usare sizeof perche' il buffer era della
dimensione giusta, _ma non_ della dimensione passata alla funzione di
lettura => sizeof era per sicurezza (nel caso il parametro fosse stato >
della dimensione del buffer).
Se il buffer e' allocato dal compilatore, ma di dimensioni maggiori del
blocco che dobbiamo leggere ovviamente non possiamo passare sizeof a
ReadFile e non esiste il pericolo di leggere oltre le dimensioni del
buffer.
L'alternativa della allocazione dinamica del buffer e', ovviamente,
sempre presente.
Infine, se ad es. si deve leggere un file di testo strutturato (ogni x
byte un record) e' possibile usare una TTable; oppure, + oop, un
discendente di TPersistent (mai provato, ma penso basti l'override di
DefineProperties).
Saluti
Paolo Arosio

 l'accesso ai file.
Anche io ho questa tendenza.
Ciao!


 Anche io ho questa tendenza.
Ahhhrrrg!! Robaccia Microsoft!!! ;PPP
Ciao, Davide DG :)

 DefineProperties).
mai provato nenche io, quindi non ti so dire...
Ciao,
Alan Solo

 io.
eh gia', tu sempre a giudicare gli altri!! ;)))
Ciao! :)
Alan