Newsgroup: it.comp.lang.delphi
Titolo: Copia di file... particolare

Ciao a tutti,
chi può suggerirmi una procedura sviluppata in assembly per delphi tale da 
permettermi la copia di un file sorgente in uno destinazione sfruttando al 
massimo la velocità dei dispositivi hardware?
Il motivo è molto semplice: Ipotizzando file nell'ordine di 4-8 Gb i tempi 
di copia con delphi diventano proibitivi; mentre ho visto che altre 
applicazioni anche banalissime riescono a fare una copia esatta del file in 
tempi decisamente molto ma molto più ridotti.
Questo mi lascia pensare che ci sia sotto qualcosa in assembly per 
velocizzare il più possibile il tutto.
Grazie a chi mi saprà indirizzare nel modo migliore.
Cooper.
PS: Devo realizzare una piccola applicazione dove necessito di convertire il 
formato di un file sorgente in un formato diverso del file destinazione; 
sulla base di un particolare algoritmo che ricevuti i dati dal sorgente li 
elabora e li trasferisce per essere scritti nel file destinazione. 

 velocizzare il pi� possibile il tutto.
Non so se sia merito dell'assembly la velocit� di trasferimento...
Per curiosit�, che metodo usi per copiare?
-- 
Jax

 del file in tempi decisamente molto ma molto pi� ridotti.
Quali sono queste applicazioni? Essendo il trasferimento il maggiore 
"collo di bottiglia", secondo me � ben difficile che tu riesca ad 
ottenere qualche vantaggio con ci� che chiedi. :-|
Ciao,
   Marco.
-- 
MARCO BREVEGLIERI
  (
http://www.marco.breveglieri.name
)

 decisamente molto ma molto piï¿œ ridotti.
Non capisco di quale versione di delphi parli, se sei in 32bit o su 
.net (parli di assembly..), e quale sia il codice che hai testato.
Se parli di tempi, dovresti poterci dare piu' informazioni su queste 
misurazioni, vale a dire: quali programmi si sono rivelati piu' veloci? 
Quali tempi hai misurato? Su quali sistemi?
Ti dico questo perchï¿œ alla base della copia di un file ci sono sempre 
le api di winzozz, quindi, quelle invocate da un prg delphi sono le 
stesse utilizzate da un altro prg... (a meno di non creare un 
meccanismo tipo download manager che copia chunck di files in parallelo 
poi li "attacca" insieme alla fine: ma qui siamo gia' alle soluzioni, 
vorrei prima poter capire lo scenario preciso in cui ti stai muovendo)
Per farla breve: dacci maggiori info.
Ciao
-- 
Morde


Uso l'oggetto stream. 


Ho trovato un convertitore di immagini (non foto) da iso ad altri formati e 
ho visto che la velocità con cui elaborava il processo di conversione era 
piuttosto veloce, direi di parecchio.
Una immagine da 4 gb l'ha convertita infatti in meno di 2 minuti circa 
contro i cinque circa di una normale copia con delphi. 


Uso delphi 2006 a 32 bit non .net.
Per il resto ho usato il mio pc, normalissimo nemmeno super-dotato :) 
sistema operativo vista, 32 bit con 2 gb di memoria ram.
 

 contro i cinque circa di una normale copia con delphi.
Il file che scrive non è lo stesso che legge: è un po' come valutare la 
velocità di trasferimento di file audio quando la partenza è un 
voluminoso WAV da un centinaio di MB, mentre il formato di arrivo è un 
MPEG3 da meno di 10 MB. :-|


 Uso l'oggetto stream.
E' un po' come il sesso... "dipende da come lo usi". :-)
Mostra un esempio di codice.


 sistema operativo vista, 32 bit con 2 gb di memoria ram.
Banalità, ma hai provato a usare la SHFileOperation e lasciare gestire 
tutto a Win? (sempre se puoi farlo)
-- 
Jax


Il file sorgente viene letto a tutti gli effetti, processato e quindi 
scritto in uno destinazione. La conversione del formato non è solo a livello 
del cambio di estensione. 

 ha scritto nel messaggio 
news:gbdcf2$ht9$1...@tdi.cu.mi.it...

Non so, però ho trovato qualcosa di più il sorgente dell'applicativo e credo 
di aver individuato la procedura che dovrebbe occuparsi della 
lettura/processione/scrittura,  è possibile postarla o preferibilmente in 
privato? 

 privato?
posta posta...
-- 
Morde

 livello del cambio di estensione.
Non ho detto che cambia solo l'estensione: ho semplicemente detto che la 
quantit� di dati da scrivere non � necessariamente uguale a quella letta.


 in privato?
Basterebbe anche solo qualche indicazione su come materialmente questa 
copia viene fatta.
Sembra che stai mantenendo il "segreto industriale" su una procedura di 
copia talmente eccelsa e innovativa che... non piace nemmeno a te. :-)
Come lavori con gli Stream che hai detto di utilizzare? Carichi tutto e 
poi trasferisci in un sol colpo? Oppure trasferisci a blocchi? Esegui 
delle conversioni nel momento in cui scrivi il file di destinazione?
Basta anche un esempio, non necessariamente il "codice di contorno" 
attorno a questa parte di interesse.


 ha scritto nel messaggio 
news:48da5724$1...@news.x-privat.org...

No no nulla del genere, ï¿œ solo che volevo essere sicuro di nn andare contro 
la licenza ne tantomeno contro lo spirito del gruppo, la procedura  ï¿œ questa 
qui:
procedure TForm1.Button3Click(Sender: TObject);
var
  src, dst: Integer;
  buf: Pointer;
  n, bytes, bytestocopy: Integer;
  lastpart: array [0..4] of Integer;
begin
  if Tag = 0 then
    begin
      Tag := 1;
      cancel := False;
      Button1.Enabled := False; Button2.Enabled := False; Button4.Enabled := 
False;
      Button3.Caption := '&Quit';
      src := INVALID_HANDLE_VALUE;
      dst := INVALID_HANDLE_VALUE;
      try
        GetMem(buf, 1 shl 20); // 1 Megabyte
        src := CreateFile(PChar(Edit1.Text), GENERIC_READ, FILE_SHARE_READ, 
nil, OPEN_EXISTING, 0, 0);
        if (src = INVALID_HANDLE_VALUE) then
          raise EInOutError.Create('Source file not found.');
        dst := CreateFile(PChar(Edit2.Text), GENERIC_WRITE, FILE_SHARE_READ, 
nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
        if (dst = INVALID_HANDLE_VALUE) then
          raise EInOutError.Create('Cannot create destination file.');
        bytestocopy := SetFilePointer(src, 0, nil, FILE_END);
        SetFilePointer(src, -sizeof(lastpart), nil, FILE_END);
        if (not ReadFile(src, lastpart, sizeof(lastpart), n, nil)) then
          raise EInOutError.Create('Source file too short.');
        if (((lastpart[0] = $21444E45) and
             (lastpart[2] = $3552454E)) or
            ((lastpart[1] = $21444E45) and
             (lastpart[3] = $4F52454E))) then
          begin
            bytestocopy := lastpart[4];
            asm
              mov eax, bytestocopy
              xchg ah, al
              rol eax, 16
              xchg ah, al
              mov bytestocopy, eax
            end;
          end;
        Dec(bytestocopy, 512*600);
        if (SetFilePointer(src, 512*600, nil, FILE_BEGIN) = -1) then
          raise EInOutError.Create('Source file too short.');
        while (bytestocopy > 0) do
          begin
            bytes := bytestocopy;
            if (bytes > 1 shl 20) then
              bytes := 1 shl 20;
            if (not ReadFile(src, buf^, bytes, n, nil)) then
              raise EInOutError.Create('Read error');
            if n = 0 then
              break;
            Dec(bytestocopy, n);
            if cancel then
              break;
            if (not WriteFile(dst, buf^, n, n, nil)) then
              raise EInOutError.Create('Write error');
            Label1.Caption := Format('Copied %d bytes', [SetFilePointer(src, 
0, nil, FILE_CURRENT)]);
            Label1.Update;
            Application.ProcessMessages;
          end;
        Label1.Caption := 'fertig.';
      except
        on e: EInOutError do
          Label1.Caption := 'Error: ' + e.Message;
      end;
      CloseHandle(src);
      CloseHandle(dst);
      Button3.Caption := '&Convert';
      Button1.Enabled := True; Button2.Enabled := True; Button4.Enabled := 
True;
      Tag := 0;
    end
  else
    cancel := True;
end;
perï¿œ tutta questa procedura qui si occupa della lettura / elaborazione / 
scrittura.   a me interessa solo eliminare la sezione di codice finalizzata 
alla elaborazione dei dati poi andrebbe sostituita con altro codice e 
individuare solo la parte relativa alla lettura e scrittura.
 

 qui:
Scusa ma non capisco questa logica: devi copiare semplicemente un file 
o devi alterare i dati in esso contenuto? Dalla procedura da te postata 
si vede che consideri delle porzioni di file e ci fai delle cose sopra, 
ma non mi e' chiaro il motivo e la funzionalità.
Ma non hai provato con un semplice copyfile?? Perche' usate questa 
procedura?
Ciao
-- 
Morde

 ha scritto nel messaggio 
news:48dcabb2$1...@newsgate.x-privat.org...

Esatto, non devo fare un semplice copyfile, devo fare delle elaborazioni sul 
file sorgente e scriverne uno destinazione. Il punto è un altro, la velocità 
nelle operazioni di lettura/scrittura che con questa procedura sono 
notevolmente più veloci di quelle classiche.
Ed è proprio questo il punto che cercavo di capire, cioè di estrapolare da 
questa procedura le parti relative alla lettura/scrittore modificando quelle 
che riguardano l'elaborazione dei dati letti e quindi la loro scrittura in 
un file di destinazione. 

 codice e individuare solo la parte relativa alla lettura e scrittura.
ciao.
Mi pare che questa procedura non faccia proprio niente di spaziale.
estrapolando solo la parte che legge e scrive:
 >      src := INVALID_HANDLE_VALUE;
 >      dst := INVALID_HANDLE_VALUE;
 >      try
 >        GetMem(buf, 1 shl 20); // 1 Megabyte
 >        src := CreateFile(PChar(Edit1.Text), GENERIC_READ,
 > FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
 >        if (src = INVALID_HANDLE_VALUE) then
 >          raise EInOutError.Create('Source file not found.');
 >        dst := CreateFile(PChar(Edit2.Text), GENERIC_WRITE,
 > FILE_SHARE_READ, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
 >        if (dst = INVALID_HANDLE_VALUE) then
 >          raise EInOutError.Create('Cannot create destination file.');
[...]
 >        while (bytestocopy > 0) do
 >          begin
 >            bytes := bytestocopy;
 >            if (bytes > 1 shl 20) then
 >              bytes := 1 shl 20;
 >            if (not ReadFile(src, buf^, bytes, n, nil)) then
 >              raise EInOutError.Create('Read error');
 >            if n = 0 then
 >              break;
 >            Dec(bytestocopy, n);
 >            if (not WriteFile(dst, buf^, n, n, nil)) then
 >              raise EInOutError.Create('Write error');
 >          end;
[...]
 >      CloseHandle(src);
 >      CloseHandle(dst);
Non ci vedo niene di strano, assembler o altro. Solo normali CreateFile,
ReadFile, WriteFile... niente magia, tutto molto normale.
Non e' che e' piuttosto il tuo codice che e' inefficiente e ci mette
piu' tempo del necessario?
ciao
Giacomo