Accelerre la lecture du fichier .

kevin2002 Messages postés 16 Date d'inscription samedi 9 février 2008 Statut Membre Dernière intervention 2 octobre 2013 - 2 févr. 2012 à 15:59
Caribensila Messages postés 2527 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 16 octobre 2019 - 3 févr. 2012 à 17:26
 kevin-now: je veux que la lecture du fichier soit tres rapide,pour un fichier de "538 Ko" la lecture byte par byte prend "78 secondes",pouvez-vous m'aide pour accelerre la lecture du fichier?.



//fonction Statistique pour determiner le nombre de chaque caracteres dans un fichier.
//Fs => fichier Source.
//AH => vecteur pour mettre les statistique ("AH" est pres initialiser dans l'appel de la procedure).
Function Statistique(Const Fs:String;Var AH:Array[0..255]of integer):Boolean;
var F,T:TFileStream;
buff:byte;
i:integer;
begin
Result:=false;
If (not FileExists(Fs))or(not FileExists(Temp)) then exit;

F:=TFileStream.Create(Fs,fmOpenRead or fmShareExclusive);
try
f.Seek(soFromBeginning,0);

for i:=1 to F.Size do begin
f.Read(buff,sizeof(buff));
AH[Buff]:=AH[Buff]+1;

// HashCallBack: procedure "Progressbar"
HashCallBack(F.Size,F.Position);
end;
finally
F.Free;
end;
Result:=true;
end;

8 réponses

Utilisateur anonyme
2 févr. 2012 à 21:35
Salut,

Tu l'as testé ton code avant de le donner ? Car mon petit doigt me dit que sous D6/D7/D2005 (et les autres c'est à voir) ton truc il compile pas et pour cause
0
Utilisateur anonyme
2 févr. 2012 à 21:51
Un bout de piste pour améliorer les performances de ton code

Function Statistique(Const Fs:String; Var AH:array of Integer):Boolean;
var
  F:TFileStream;
  buff:byte;
  i:integer;
  SizeFile:Int64;
begin
  Result:=false;
  If (FileExists(Fs))And (FileExists(FS)) then
    Begin
      F:=TFileStream.Create(Fs,fmOpenRead or fmShareExclusive);
      try
        f.Seek(soFromBeginning,0);
        SizeFile:=F.Size;
        for i:=1 to SizeFile do
          begin
            f.Read(buff,1);
            AH[Buff]:=AH[Buff]+1;
            // HashCallBack: procedure "Progressbar"
            //HashCallBack(SizeFile,i);
          end;
      finally
        F.Free;
      end;
      Result:=true;
    end;
End;


Ceci dit : Il est évident que le traitement que tu veux faire sera long car tu lis ton fichier bytes à bytes. La notion de flux est un peu plombée en terme d'intéret, vu ce que tu fais
0
Caribensila Messages postés 2527 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 16 octobre 2019 18
3 févr. 2012 à 02:18
Ceci dit : Il est évident que le traitement que tu veux faire sera long car tu lis ton fichier bytes à bytes. La notion de flux est un peu plombée en terme d'intéret, vu ce que tu fais.


Francky a raison.
Mais ce n'est pas que la notion de flux est un peu plombée... c'est qu'elle n'existe pas du tout !

Le problème est que tu lis byte-à-byte un fichier sur le disque dur, avec autant d'accès à ce DD que de bytes...

La solution est de lire dans la Ram en utilisant TMemoryStream.LoadFromFile.
0
cs_MAURICIO Messages postés 2106 Date d'inscription mardi 10 décembre 2002 Statut Modérateur Dernière intervention 15 décembre 2014 5
3 févr. 2012 à 10:28
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
3 févr. 2012 à 12:24
Salut,

ou encore lire les données en une passe avec le TFileStream et en utilisant les pointeurs ...

voici un exemple avec la temps d'exécution 0,01 sec. pour 3324 caractères.
[hr][b]implementation


/b{$R *.dfm}

 // ajouté pour mesurer le temps d'exécution
function MyGetTickCount: Int64;
[b]var
  /blpPerformanceCount,
    lpFrequency: Int64;
[b]begin
  if not /bQueryPerformanceCounter(lpPerformanceCount) [b]then
    /blpPerformanceCount :=  GetTickCount
  [b]else
  begin
    /bQueryPerformanceFrequency(lpFrequency);
    lpPerformanceCount := (lpPerformanceCount * 1000)  div  lpFrequency
  end;

  result : = lpPerformanceCount;
end;

   // on crée un type approprié
  // avec son pointeur
[b]type
  /bPCharCountArray  =  ^TCharCountArray;
  TCharCountArray =   array [Byte] of Integer;

   // pour l'affichage final
[b]var
  /bTotalChar: Integer;

  //fonction Statistique pour determiner le nombre de chaque caracteres dans un fichier.
  //Fs  => fichier Source.
  //AH = > vecteur pour mettre les statistique ("AH" est pres initialiser dans l'appel de la procedure).
   // AH devient un pointeur ... on ne passe plus une copie du tableau
function  Statistique(const Fs: stringconst AH: PCharCountArray):
  Boolean;
[b]var
  /bF, T: TFileStream;
  Buffer: string;
  buff: PByte;
  i: integer;
[b]begin
  /bResult : = false;
  //if (not FileExists(Fs)) or (not FileExists(Temp)) then
    //exit;

  F :=  TFileStream.Create(Fs, fmOpenRead  or  fmShareExclusive);
  [b]try
    /bTotalChar : = F.Size;
    f.Seek(soFromBeginning, 0);
    SetLength(Buffer, F.Size);
    Buff :=  @Buffer[1];
     // lecture en une passe des données
    f.ReadBuffer(buffer[1], F.Size);
    // traitement par pointeur
     for  i : = 1 to F.Size [b]do
    begin
      /bAH^[Buff^] :=  AH^[Buff^] + 1;
      Inc(Cardinal(Buff));

       //ici tu perd un Max de temps
      // HashCallBack: procedure "Progressbar"
      //HashCallBack(F.Size, I);
     end ;
  [b]finally
    /bF.Free;
  end;
  Result : = true;
end;

procedure TForm11.Button1Click(Sender: TObject);
[b]var
  /bAH: TCharCountArray;
  iI: Integer;
  StartTime: Cardinal;
[b]begin
  /b// mise à zéro du tableau
  for iI :=  Low(AH)  to  High(AH) [b]do
    /bAH[iI] : = 0;
   // début
  StartTime : =  GetTickCount;
   if  Statistique('Unit11.pas', @AH) [b]then
  try
    /bCaption : =  Format('Exécuté en %.2f secondes pour %d Caractère(s)', [(MyGetTickCount - StartTime)/1000, TotalChar]);
     // l'affichage ne compte pas dans le temps d'exécution
    Memo1.Lines.BeginUpdate;
    Memo1.Clear;
    for iI : = Low(AH) to High(AH) [b]do
      /bMemo1.Lines.Add(Format('%d fois le caractère %s #%d', [AH[iI], Chr(iI), iI]));
  [b]finally
    /bMemo1.Lines.EndUpdate;
  end;
end;

end.
[hr]
Voilà ceci devrait répondre à ta question

[hr]@+Cirec
[hr]
0
Utilisateur anonyme
3 févr. 2012 à 13:05
Mais ce n'est pas que la notion de flux est un peu plombée... c'est qu'elle n'existe pas du tout !


Ben si c'est plombée (Nom de dioux ) de part ce qu'il veut faire en vue de la méthode qu'il emploie : Quand tu fais Lille-Tours tu prends l'A3 ben imagine que l'autoroute le commandant Francky et sa patrouille ils condamnent les 3 voies sur 4 et qu'en plus ils arrêtent les voitures une par une pour les contrôler, c'est qui le kiki qui va gueuler au péage devant le guichetier plutôt que de sortir sa CB , ben c'est Cari ? "Va donc chez affelou, t'achetez des lunettes : Moi payer que nenni mon ami" qui va dire le Kiki à a mémère et qu'il aura raison le kiki car si tu prends l'autoroute c'est pas pour que les voitures passent au compte goutte. Ben là c'est à peu près ce qui veut faire.

Ps : Fait ça sur l'A15 un vendredi soir à 18h, t'es un homme mort. Espérance de vie 78 secondes et encore si tu as un bon flux.
0
Caribensila Messages postés 2527 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 16 octobre 2019 18
3 févr. 2012 à 15:58
@Francky
De toute façon, si "le commandant Francky et sa patrouille" sont sur l'A3, le Kiki y passe par Rouen pour faire Lille-Tours !
Pas fou le Kiki !

@ Cirec
Puisqu'on me chipote au péage, je chipote aussi pour le passage de paramètre par pointeur (y'a pas de raison) :

//if Statistique('Unit1.pas', @AH) then //Passage par pointeur de pointeur: pas bô.
if Statistique('Unit1.pas', @AH[Low(AH)]) then //Passage par pointeur sur la 1ère cellule du tableau: bô.
0
Caribensila Messages postés 2527 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 16 octobre 2019 18
3 févr. 2012 à 17:26
@ Cirec

Je retire ce que j'ai dit (encore raté une belle occasion de me taire, moi !).

Après vérif :
Integer(@AH) := Integer(@AH[0])
0