ReadFile // WriteFile // Taille du buffer

Résolu
Inekman Messages postés 291 Date d'inscription dimanche 2 février 2003 Statut Membre Dernière intervention 30 juin 2006 - 4 avril 2005 à 00:56
Inekman Messages postés 291 Date d'inscription dimanche 2 février 2003 Statut Membre Dernière intervention 30 juin 2006 - 6 avril 2005 à 00:19
Salut les amis, j'ai un problème de lecture avec l'api readfile.



J'ai un buffer de 64ko qui contient ce que lit l'api sauf que quand
j'arrive à la fin du fichier que je suis en train de lire et que la
taille restante à lire est inférieure à la taille du buffer, alors
l'api ne lit rien du tout et la boucle boucle
sans fin puisque la taille lue reste toujours inférieure à la taille
totale du fichier...je sais pas si vous avez compris mais moi je sèche
:-(



buffer: array[0..65535] of char;





ZeroMemory(@buffer, sizeof(buffer));





[...]





Source := CreateFile(PChar(src), GENERIC_READ, 0, nil, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, 0);


Dest:= CreateFile(PChar(dest), GENERIC_WRITE, 0, nil, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);





[...]





alire := sizeof(buffer);


aecrire := alire;


totalecrit := 0;





while totalecrit < total do


begin


// si "alire" est inférieur à la taille du buffer,


// alors la fonction ne lit rien du tout :(





ReadFile(Source, buffer, alire, lu, nil);


WriteFile(Dest, buffer, aecrire, ecrit, nil);



totalecrit := totalecrit + ecrit;


if totalecrit + alire > total then


begin


alire := total - totalecrit ;


aecrire := alire;


end;


end;

14 réponses

WhiteHippo Messages postés 1154 Date d'inscription samedi 14 août 2004 Statut Membre Dernière intervention 5 avril 2012 3
5 avril 2005 à 00:51
Moi j'suis comme Kenavo, y'a quelquechose qui me plait pas non plus !!!!
C'est que tu n'utilises pas la taille du fichier !!!

Bon j'ai fait vite (j'suis peut être passé à côté de quelquechose) un bout de code (mais qui fonctionne) avec les API windows (sauf pour l'allocation du buffer) puisque cela te tenait tellement à coeur
N.B. Je sais, il n'y a pas beaucoup de commentaires mais je pense que les variables utilisées parlent d'elles mêmes.

const
TAILLE_BUFFER = 65536 ; // Ou plus pour un nombre de passes de copie inférieur


type
PBuffer = ^TBuffer ;
TBuffer = array[0..TAILLE_BUFFER-1] of char ;


procedure CopieFichier( Source, Dest : string ) ;
var
SourceHandle : THANDLE ;
DestHandle : THANDLE ;
Erreur : DWORD ;
TailleFichierSourceLow : Cardinal ;
TailleFichierSourceHigh : Cardinal ;
TailleFichierSource : int64 ;
NombreOctetsRestants : int64 ;
SourceOctetsLus : Cardinal ;
DestOctetsEcrits : Cardinal ;
SourceOctetsALire : Cardinal ;
DestOctetsAEcrire : Cardinal ;
Resultat : Boolean ;


PtrBuffer : PBuffer ;
begin
new ( PtrBuffer ) ;
if ( PtrBuffer = NIL ) then
begin
Messagedlg('Impossible d''allouer de la mémoire pour le buffer.',mtError,[mbOK],0);
Exit ;
end ;
try
// !! Attention Avec FILE_FLAG_NO_BUFFERING à la place de FILE_ATTRIBUTE_NORMAL
// ça ne fonctionne pas parce que :
// "An application must meet certain requirements when working with files
// opened with FILE_FLAG_NO_BUFFERING (c.f. Win32 Programmer's References)"
SourceHandle := CreateFile(PChar(Source), GENERIC_READ, 0, NIL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (SourceHandle = INVALID_HANDLE_VALUE) then
begin
Erreur := GetLastError() ;
Messagedlg(Format('Erreur %d à l''ouverture du fichier source %s.', [Erreur,Source]),mtError,[mbOK],0);
Exit ;
end ;
DestHandle := CreateFile(PChar(dest), GENERIC_WRITE, 0, NIL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);
if (DestHandle = INVALID_HANDLE_VALUE) then
begin
// Traitement erreur : Message, exception, etc...
Erreur := GetLastError() ;
CloseHandle( SourceHandle );
Messagedlg(Format('Erreur %d à l''ouverture du fichier destination %s.', [Erreur,Dest]),mtError,[mbOK],0);
Exit ;
end ;


TailleFichierSourceLow := 0 ;
TailleFichierSourceHigh := 0 ;
TailleFichierSourceLow := GetFileSize( SourceHandle, @TailleFichierSourceHigh ) ;
if ( TailleFichierSourceLow = $FFFFFFFF ) then
begin
Erreur := GetLastError() ;
Messagedlg(Format('Erreur %d : Impossible d''obtenir la taille du fichier %s.', [Erreur,Dest]),mtError,[mbOK],0);
CloseHandle(SourceHandle);
CloseHandle(DestHandle);
Exit ;
end ;
TailleFichierSource := ( TailleFichierSourceHigh shl 32 ) + TailleFichierSourceLow ;


NombreOctetsRestants := TailleFichierSource ;
while ( NombreOctetsRestants > 0 ) do
begin
if ( NombreOctetsRestants < TAILLE_BUFFER ) then
begin
SourceOctetsALire := NombreOctetsRestants ;
DestOctetsAEcrire := NombreOctetsRestants ;
end else
begin
SourceOctetsALire := TAILLE_BUFFER ;
DestOctetsAEcrire := TAILLE_BUFFER ;
end ;


SourceOctetsLus := 0 ;
FillChar( PtrBuffer^, TAILLE_BUFFER, #0 ) ;
Resultat := ReadFile ( SourceHandle, PtrBuffer^, SourceOctetsALire, SourceOctetsLus , nil ) ;
if ( Resultat and ( SourceOctetsLus = 0 ) ) then
begin
// Fin du fichier
end else begin
if ( not Resultat ) or ( SourceOctetsLus <> SourceOctetsALire ) then
begin
Messagedlg( format( 'Erreur : Nombre d''octets lus %d différents du nombre attendu %d.'
,[SourceOctetsLus,SourceOctetsALire]),mtError,[mbOK],0);
CloseHandle(SourceHandle);
CloseHandle(DestHandle);
Exit ;
end ;
end ;


DestOctetsEcrits := 0 ;
Resultat := WriteFile ( DestHandle, PtrBuffer^, DestOctetsAEcrire, DestOctetsEcrits , nil ) ;
if ( not Resultat ) or ( DestOctetsEcrits <> DestOctetsAEcrire ) then
begin
Messagedlg( format( 'Erreur : Nombre d''octets écrits %d différents du nombre attendu %d.'
,[DestOctetsEcrits,DestOctetsAEcrire]),mtError,[mbOK],0);
CloseHandle(SourceHandle);
CloseHandle(DestHandle);
Exit ;
end ;
NombreOctetsRestants := NombreOctetsRestants - SourceOctetsALire ;
end ;
CloseHandle(SourceHandle);
CloseHandle(DestHandle);
finally
dispose( PtrBuffer );
PtrBuffer := NIL ;
end ;
end ;

Cordialement.
3
Rejoignez-nous