IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Delphi Discussion :

Convertir un gros fichier en plusieurs moins gros ?


Sujet :

Langage Delphi

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    624
    Détails du profil
    Informations personnelles :
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 624
    Points : 199
    Points
    199
    Par défaut Convertir un gros fichier en plusieurs moins gros ?
    Bonjour à tous,

    Je sais qu'il existe pas mal de post à propos de ce sujet mais la petite différence (et c'est là que ça pose problème)
    c'est que je dois éclater mon gros fichier (~800 à 900Mo) suivant une chaîne de caractère. Je n'ai pas trouver ça.

    Pour info, mon gros fichier est un fichier que je reçois qui est en fait la concaténation de fichiers XML, donc avec
    à chaque fois des balises de début de fichier XML et de fin.

    J'ai ma propre routine qui fonctionne très bien mais qui est affreusement lente ci-dessous:

    Le code ci-dessous correspond à mon process principal, je fais des fichiers de 1000 notices XML,
    j'utilise ma fonction scanBig pour rechercher les notices dans mon gros fichiers. Elle fonctionne très bien
    et est assez rapide sur des petites chaînes de caractère.

    Je suis ***obligé*** de passer par un prog delphi car c'est inclus dans un autre projet, je n'ai pas la possibilité
    de passer par un programme intermédiaire, etc....

    Pour vous donner un ordre d'idée, sur un fichier test de 450Mo, sur mon i7, rien que pour créer la première tranche de 1000 notices
    cela prend au moins 5 à 6 minutes.....et il y a env. 10 000 notices dans ce test.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
            c       := PChar(Page);
            k       := 1;
            foo     := '';
            notice  := '';
     
            Pb1.Position  := 0;
            Pb1.min       := 0;
            Pb1.Max       := length(Page);
     
            Taille        := 0;
     
            while scanbig('<patent-application-publication>', '</patent-application-publication>', c, notice) do
            begin
              foo     := foo + '<patent-application-publication>' + notice + '</patent-application-publication>' + #13#10;
              Taille  := Taille + length(notice);
     
              if ((k mod 1000)=0) then
              begin
                FD:=TFileStream.Create(ExtractFilePath(Application.ExeName)+cPathInput+'\'+cPathXml+'\'+MyCurrentDir+'\'+inttostr(k)+'.xml', fmCreate);
                Try
                  FD.Write(PChar(foo)^, Length(foo));
                Finally
                  FD.Free;
                End;
                foo := '';
              end;
              inc(k);
     
              Pb1.position  := Taille;
            end;
     
            // On sauvegarde le reste
            FD:=TFileStream.Create(ExtractFilePath(Application.ExeName)+cPathInput+'\'+cPathXml+'\'+MyCurrentDir+'\'+inttostr(k)+'.xml', fmCreate);
            Try
              FD.Write(PChar(foo)^, Length(foo));
            Finally
              FD.Free;
            End;
            foo := '';
          End;
    Ma fonction bigScan maintenant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    function ScanBig(const Search1, Search2: string; var Ch: PChar; var Text: string): Boolean;
    var
      Ch1, Ch2: PChar;
    begin
      Result:=False;
      if not Assigned(Ch) then
        Exit;
      Ch1 := StrPos(Ch, PChar(Search1));
      if Ch1 <> nil then
      begin
        Ch := Ch1 + Length(Search1);
        Ch2 := StrPos(Ch, PChar(Search2));
        if Ch2 <> nil then
        begin
          SetString(Text, Ch, Ch2 - Ch);
          Ch := Ch2 + Length(Search2);
        end
        else
        begin
          Text := StrPas(Ch);
          Ch := nil;
        end;
        Result := True;
      end;
    end; {* func ScanBig *}

    Merci pour vos conseils !!!!

  2. #2
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 448
    Points
    28 448
    Par défaut
    1) pourquoi passer par des PChar pour la recherche ?

    2) pourquoi NE PAS passer par des PChar pour l'extraction ?

    si je comprend bien le fichier est complètement en mémoire (est-ce une nécessité ?)

    ScanBig devrait retourner un PChar sur le début de la chaîne recherchée (Ch) et un Integer sur la longueur utile (Ch2-Ch) au lieu de faire un SetString(Text, Ch, Ch2 - Ch); qui en fait une copie pour rien.

    au lieu de concaténer tout dans Foo, soit j'ouvrirais le fichier dès le départ pour l'alimenter au fur et à mesure, en passant à k+1 le cas échéant.
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    624
    Détails du profil
    Informations personnelles :
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 624
    Points : 199
    Points
    199
    Par défaut
    Salut Paul,

    Je vais essayer de répondre à tes questions.

    1) pourquoi passer par des PChar pour la recherche ?
    J'ai toujours pensé que c'était plus rapide de passer par un PChar pour rechercher un élément dans une chaîne,
    je me trompe peut être...

    2) pourquoi NE PAS passer par des PChar pour l'extraction ?
    j'avoue....c'est vrai que je mixe un peu les méthodes là... en contradiction avec ce que j'ai écris au dessus
    tu pourrais me montrer comment faire avec un PChar pour l'extraction ?

    si je comprend bien le fichier est complètement en mémoire (est-ce une nécessité ?)
    Non, aucun nécessité, ça pause problème ? ou c'est juste pour gagner un peu de temps de chargement ?


    ScanBig devrait retourner un PChar sur le début de la chaîne recherchée (Ch) et un Integer sur la longueur utile (Ch2-Ch) au lieu de faire un SetString(Text, Ch, Ch2 - Ch); qui en fait une copie pour rien.
    J'ai voulu retourner directement la chaîne recherchée tout simplement...

    au lieu de concaténer tout dans Foo, soit j'ouvrirais le fichier dès le départ pour l'alimenter au fur et à mesure, en passant à k+1 le cas échéant.
    Disons que j'ouvre et je ferme le fichier tous les 1000 notices, donc je pense ne pas gaspiller trop de temps sur ça. mais bon par soucis d'optimisation (et c'est le but ici)
    voici ma petite modif.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
            FD            := TFileStream.Create(ExtractFilePath(Application.ExeName)+cPathInput+'\'+cPathXml+'\'+MyCurrentDir+'\'+inttostr(k)+'.xml', fmCreate);
            Try
              while scanbig('<patent-application-publication>', '</patent-application-publication>', c, notice) do
              begin
                foo     := '<patent-application-publication>' + notice + '</patent-application-publication>' + #13#10;
                FD.Write(PChar(foo)^, Length(foo));
                Taille  := Taille + length(notice);
     
                if ((k mod 100)=0) then
                begin
                  FD.Free;
                  FD:=TFileStream.Create(ExtractFilePath(Application.ExeName)+cPathInput+'\'+cPathXml+'\'+MyCurrentDir+'\'+inttostr(k)+'.xml', fmCreate);
                end;
                inc(k);
                Pb1.position  := Taille;
              end;
            Finally
              FD.Free;
            End;
          End;

    Il est évident que c'est ma recherche ScanBig qui est à améliorer, si tu as quelques lignes de code en stock je suis preneur !
    surtout que pour SetString

    en tout cas merci pour tes conseils toujours pertinents !
    Amicalement,
    Bruno

  4. #4
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 519
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 519
    Points : 25 037
    Points
    25 037
    Par défaut
    Quelle version de Delphi ?
    Si 3 à 7, la concaténation de chaine est très lente
    D2007 et plus, comme FastMM est intégré, la concaténation de chaine est 100x plus rapide qu'en D7

    Personnellement, je me suis fait une fonction de recherche SearchBinaryInFile qui me renvoie la position de la donnée trouvée dans le fichier
    Ainsi en une seule fois, j'ai TOUTES les positions de l'occurrence
    Il faudrait modifier la fonction SearchBinaryInFile pour chercher plusieurs chaines à la fois et retourner un tableau de tableau de position

    Tu peux aussi faire comme moi, l'appeler deux fois de suite, si cela donne le même nombre d'offset, ton fichier est bien complet avec balise début et balise de fin
    Avec les deux tableaux d'offset, tu pourras partir de OffsetDebut jusqu'à OffSetFin pour découper chaque section du fichier


    Je n'ai pas d'exemple sur du XML, je l'utilise dans le cadre de la surveillance de fichier DMP qui apparaissent par dizaines de milliers suite à des plantages sur de vieux modules qui boucle dans leur plantage

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
     
    unit ScanMiniDump_MainForm;
     
    interface
     
    uses
      Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, System.Types,
      Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls;
     
     
     
    type
      TScanMiniDumpForm = class(TForm)
        btnScanMiniDump: TButton;
        lblScanMiniDump: TLabel;
        MemoScanMiniDump: TMemo;
        pnlScanMiniDumpActions: TPanel;
        lblScanMiniDumpCount: TLabel;
        procedure btnScanMiniDumpClick(Sender: TObject);
        procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
      private
        { Déclarations privées }
        FScanning: Boolean;
        FScannedCount: Integer;
        FScanAborted: Boolean;
        FTickProcessMessages: DWORD;
        procedure ScanMiniDumpProgress(const ADirectory: TFileName);
      public
        { Déclarations publiques }
      end;
     
    var
      ScanMiniDumpForm: TScanMiniDumpForm;
     
    implementation
     
    uses {$WARN UNIT_PLATFORM OFF}Vcl.FileCtrl{$WARN UNIT_PLATFORM ON};
     
    {$R *.dfm}
     
    type
      TScanMiniDumpProgressEvent = procedure(const ADirectory: TFileName) of object;
     
    procedure ScanMiniDump(const ADirectory: TFileName; AExeFileNames: TStrings; AProgressEvent: TScanMiniDumpProgressEvent = nil); forward;
     
     
    procedure TScanMiniDumpForm.btnScanMiniDumpClick(Sender: TObject);
    var
      Dir: string;
    begin
      if FScanning then
      begin
        FScanAborted := MessageDlg('Arrêter le scan ?', mtConfirmation, mbYesNo, 0) = mrYes;
        Exit;
      end;
     
      Dir := ExtractFileDir(Application.ExeName);
      if Vcl.FileCtrl.SelectDirectory('Dossier des Mini Dump', '', Dir, [sdNewUI, sdShowShares, sdShowEdit]) then
      begin
        FScanning := True;
        try
          FScannedCount := 0;
          FScanAborted := False;
          MemoScanMiniDump.Lines.Clear();
          ScanMiniDump(Dir, MemoScanMiniDump.Lines, ScanMiniDumpProgress);
        finally
          FScanning := False;
        end;
      end;
    end;
     
    procedure TScanMiniDumpForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    begin
      if FScanning then
      begin
        FScanAborted := MessageDlg('Arrêter le scan ?', mtConfirmation, mbYesNo, 0) = mrYes;
        CanClose := FScanAborted;
        Exit;
      end;
    end;
     
    procedure TScanMiniDumpForm.ScanMiniDumpProgress(const ADirectory: TFileName);
    begin
      Inc(FScannedCount);
      lblScanMiniDumpCount.Caption := IntToStr(FScannedCount) + ' dossiers/fichiers scannés';
      lblScanMiniDump.Caption := ADirectory;
      if FScanAborted then
        Abort;
      // Pour que l'on puisse voir la progression, on réagit de temps en temps !
      if (GetTickCount() - FTickProcessMessages) > 1000 then
      begin
        Application.ProcessMessages();
        FTickProcessMessages := GetTickCount();
      end;
    end;
     
    procedure ScanMiniDump(const ADirectory: TFileName; AExeFileNames: TStrings; AProgressEvent: TScanMiniDumpProgressEvent = nil);
     
      function SearchBinaryInFile(const FileName: string; const SearchBinary: TByteDynArray; out OffSets: TInt64DynArray; KeepOffSet: Boolean = False; Threshold: Integer = MaxInt; AcceptOverlap: Boolean = False): Integer;
      const
         BUF_SIZE: Integer = 1024;
         ZERO: Int64 = 0;
         FILE_BEGIN = 0;
         FILE_CURRENT = 1;
         FILE_END = 2;
      var
         FileToSearch: Integer;
         FileLength, iReaded: Int64;
         SearchBuf: array of Byte;
         iSearchBufPos, iSearch, iMark, iCountFound, iRememberFound, iRememberOverlap: Integer;
         SearchLen: Integer;
         AmtTransferred: Integer;
         LastFound: Boolean;
      begin
         SearchLen := Length(SearchBinary);
     
         Result := 0;
         if SearchLen <= 0 then
           Exit;
     
         SetLength(SearchBuf, BUF_SIZE);
         iReaded := 0;
     
         FileToSearch := FileOpen(FileName, fmOpenRead);
         if FileToSearch < 0 then
           Exit;
         try
            FileLength := FileSeek(FileToSearch, ZERO, FILE_END);
            FileSeek(FileToSearch, ZERO, FILE_BEGIN);
     
            iCountFound := 0;
     
            while iReaded < FileLength do
            begin
               AmtTransferred := FileRead(FileToSearch, SearchBuf[0], BUF_SIZE); // [0] parce que c'est un tableau dynamique
               iRememberFound := iCountFound;
               iRememberOverlap := iRememberFound;
               iSearchBufPos := 0;
               iSearch := 0;
               LastFound := False;
     
               while iSearchBufPos < AmtTransferred do
               begin
                  // Comparaison Octet par Octet du Tableau d'Octet recherché
                  for iMark := iCountFound to SearchLen - 1 do // -1 car type Dyn Array
                  begin
                     iSearch := iSearchBufPos + iMark - iRememberFound;
                     if iSearch >= AmtTransferred then
                        Break;
     
                     if SearchBuf[iSearch] = SearchBinary[iMark] then
                     begin
                        Inc(iCountFound);
     
                        LastFound := iCountFound >= SearchLen;
                        if LastFound then
                        begin
                           Inc(Result);
     
                           if KeepOffSet then
                           begin
                              SetLength(OffSets, Length(OffSets) + 1);
                              if AcceptOverlap then
                                OffSets[High(OffSets)] := iReaded + iSearchBufPos - iRememberOverlap
                              else
                                OffSets[High(OffSets)] := iReaded + iSearchBufPos - iRememberFound;
                           end;
     
                           if Result = Threshold then
                             Exit;
     
                           if AcceptOverlap then
                           begin
                             if iRememberOverlap = 0 then
                               Inc(iSearchBufPos, 1)
                             else
                               Dec(iRememberOverlap);
                           end
                           else
                             Inc(iSearchBufPos, SearchLen - iRememberFound);
     
                           iCountFound := 0;
                           iRememberFound := 0;
                           Break;
                        end;
                     end else begin
                        iCountFound := 0;
                        iRememberFound := 0;
                        Break;
                     end;
                  end;
     
                  if iSearch >= AmtTransferred then
                    Break;
     
                  if LastFound then
                    LastFound := False
                  else
                    Inc(iSearchBufPos, 1);
               end;
               Inc(iReaded, AmtTransferred);
            end;
         finally
            FileClose(FileToSearch);
         end;
      end;
     
      function SearchLastZero(P: PChar; Len: Integer): Integer;
      begin
        for Result := Len-1 downto 0 do
          if P[Result] = #0 then
            Exit;
        Result := -1;
      end;
     
      procedure ScanMiniDumpExtractExeName(const AFileName: TFileName; AExeNames: TStrings);
      const
        PATTERN_EXE: string = '.exe'; // en UNICODE !!!
        PATTERN_USER: string = 'HOMEPATH'; // en UNICODE !!!
        PATTERN_HOST: string = 'COMPUTERNAME'; // en UNICODE !!!
      var
        SearchBinary: TByteDynArray;
        FoundBinary: PChar;
        OffSetsExe, OffSetsUser, OffSetsHost: TInt64DynArray;
        I, LastZero: Integer;
        FS: TFileStream;
        S, Extraction: string;
        SL: TStringList;
      begin
        // ---- Recherches ----
     
        // ---- EXE ----
        SetLength(SearchBinary, Length(PATTERN_EXE) * SizeOf(Char));
        Move(PChar(PATTERN_EXE)^, SearchBinary[0], Length(SearchBinary));
     
        SearchBinaryInFile(AFileName, SearchBinary, OffSetsExe, True);
     
        // ---- USER ----
        SetLength(SearchBinary, Length(PATTERN_USER) * SizeOf(Char));
        Move(PChar(PATTERN_USER)^, SearchBinary[0], Length(SearchBinary));
     
        SearchBinaryInFile(AFileName, SearchBinary, OffSetsUser, True);
     
        // ---- HOST ----
        SetLength(SearchBinary, Length(PATTERN_HOST) * SizeOf(Char));
        Move(PChar(PATTERN_HOST)^, SearchBinary[0], Length(SearchBinary));
     
        SearchBinaryInFile(AFileName, SearchBinary, OffSetsHost, True);
     
        // ---- Lectures ----
     
        FS := TFileStream.Create(AFileName, fmOpenReadWrite);
        try
          GetMem(FoundBinary, (MAX_PATH+1) * SizeOf(Char));
          try
            Extraction := '';
     
            // ---- EXE ----
            SL := TStringList.Create();
            try
              SL.Duplicates := dupIgnore;
              SL.Sorted := True;
              for I := Low(OffSetsExe) to High(OffSetsExe) do
              begin
                // blabla.exe
                FS.Seek(OffSetsExe[I] - ((MAX_PATH - Length(PATTERN_EXE)) * SizeOf(Char)), soBeginning);
                FS.Read(FoundBinary^, MAX_PATH * SizeOf(Char)); // en UNICODE !!!
                FoundBinary[MAX_PATH] := #0;
                LastZero := SearchLastZero(FoundBinary, MAX_PATH); // on exclue le dernier que l'on force !
                if LastZero >= 0 then
                begin
                  SetLength(S, MAX_PATH);
                  Move(FoundBinary[LastZero+1], S[1], (MAX_PATH-LastZero-1)* SizeOf(Char));
                end
                else
                  S := FoundBinary;
     
                if Pos('ComSpec=', S) = 0 then
                  SL.Add(Trim(S));
              end;
     
              Extraction := SL.CommaText;
            finally
              SL.Free();
            end;
     
            // ---- USER ----
            for I := Low(OffSetsUser) to High(OffSetsUser) do
            begin
              // USER=blabla
              FS.Seek(OffSetsUser[I], soBeginning);
              FS.Read(FoundBinary^, MAX_PATH * SizeOf(Char)); // en UNICODE !!!
              FoundBinary[MAX_PATH] := #0;
              S := FoundBinary;
     
              Extraction := Extraction + Tabulator + Trim(S);
            end;
     
            // ---- HOST ----
            for I := Low(OffSetsHost) to High(OffSetsHost) do
            begin
              // HOST=blabla
              FS.Seek(OffSetsHost[I], soBeginning);
              FS.Read(FoundBinary^, MAX_PATH * SizeOf(Char)); // en UNICODE !!!
              FoundBinary[MAX_PATH] := #0;
              S := FoundBinary;
     
              Extraction := Extraction + Tabulator + Trim(S);
            end;
     
            AExeNames.Add(Trim(Extraction));
     
          finally
            FreeMem(FoundBinary);
          end;
        finally
          FS.Free();
        end;
      end;
     
    var
      Results: TStringList;
      Dir: TFileName;
      Path, Filter: string;
      sr: TSearchRec;
    begin
      if AExeFileNames is TStringList then
        Results := TStringList(AExeFileNames)
      else
        Results := TStringList.Create();
      try
        Results.Duplicates := dupIgnore;
        Results.Sorted := True;
     
        Path := IncludeTrailingPathDelimiter(ADirectory);
        Filter := Path + '*.dmp';
     
        try
          if Assigned(AProgressEvent) then
            AProgressEvent(Path);
     
          // Les Fichiers !
          if FindFirst(Filter, faNormal, sr) = 0 then
          begin
            try
              repeat
                ScanMiniDumpExtractExeName(Path + sr.Name, Results);
                if Assigned(AProgressEvent) then
                  AProgressEvent(Path + sr.Name);
                DeleteFile(Path + sr.Name);
              until FindNext(sr) <> 0;
            finally
              FindClose(sr);
            end;
          end;
     
          // Les Dossiers !
          Filter := Path + '*';
          if FindFirst(Filter, faDirectory, sr) = 0 then
          begin
            try
              repeat
                if ((sr.Attr and faDirectory) = faDirectory) and (sr.Name <> '.') and (sr.Name <> '..') then
                begin
                  Dir := Path + sr.Name;
                  ScanMiniDump(Dir, Results, AProgressEvent);
                end;
     
              until FindNext(sr) <> 0;
            finally
              FindClose(sr);
            end;
          end;
     
        finally
          if AExeFileNames <> Results then
            AExeFileNames.Assign(Results);
        end;
      finally
        if AExeFileNames <> Results then
          Results.Free();
      end;
    end;
     
     
     
     
     
     
    end.
    Code dfm : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
     
    object ScanMiniDumpForm: TScanMiniDumpForm
      Left = 500
      Top = 235
      Caption = 'Scan Mini Dump'
      ClientHeight = 400
      ClientWidth = 784
      Color = clBtnFace
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clWindowText
      Font.Height = -11
      Font.Name = 'Tahoma'
      Font.Style = []
      OldCreateOrder = True
      Position = poScreenCenter
      OnCloseQuery = FormCloseQuery
      PixelsPerInch = 96
      TextHeight = 13
      object MemoScanMiniDump: TMemo
        Left = 0
        Top = 39
        Width = 784
        Height = 361
        Align = alClient
        ReadOnly = True
        ScrollBars = ssVertical
        TabOrder = 0
        WordWrap = False
      end
      object pnlScanMiniDumpActions: TPanel
        Left = 0
        Top = 0
        Width = 784
        Height = 39
        Align = alTop
        BevelOuter = bvLowered
        TabOrder = 1
        DesignSize = (
          784
          39)
        object lblScanMiniDump: TLabel
          Left = 3
          Top = 23
          Width = 780
          Height = 13
          Anchors = [akLeft, akTop, akRight]
          AutoSize = False
          Caption = '...'
          EllipsisPosition = epPathEllipsis
          ExplicitWidth = 596
        end
        object lblScanMiniDumpCount: TLabel
          Left = 203
          Top = 4
          Width = 12
          Height = 13
          Caption = '...'
        end
        object btnScanMiniDump: TButton
          Left = 1
          Top = 1
          Width = 196
          Height = 22
          Caption = 'Scan Mini Dump'
          TabOrder = 0
          OnClick = btnScanMiniDumpClick
        end
      end
    end
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  5. #5
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    624
    Détails du profil
    Informations personnelles :
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 624
    Points : 199
    Points
    199
    Par défaut
    Salut shaiLeTroll,

    Merci pour ton code, je vais voir ce que je peux utiliser, détourner pour arriver à mes fins dans mon programme.

    J'avais oublié de préciser sous D7... je sais je sais c'est super vieux...

    Cdlt,
    Bruno

  6. #6
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 448
    Points
    28 448
    Par défaut
    ce qui n'est pas bon c'est cette partie

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
     while scanbig('<patent-application-publication>', '</patent-application-publication>', c, notice) do
              begin
                foo     := '<patent-application-publication>' + notice + '</patent-application-publication>' + #13#10;
                FD.Write(PChar(foo)^, Length(foo));
                Taille  := Taille + length(notice);
    qui faudrait remplace par

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
     while scanbig('<patent-application-publication>', '</patent-application-publication>', c, ch1, len) do
              begin
                FD.Write(ch1^, Len);
                Taille  := Taille + len;
    où ch1 est la position de la balise ouvrante dans c et len la longueur à copier.

    avec cela tu évites de copier dans "notice" le contenu du texte, puis de le concaténé à deux constantes qui sont déjà dans la source...ça fait de grosses économie en temps de traitement de chaînes.
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  7. #7
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    624
    Détails du profil
    Informations personnelles :
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 624
    Points : 199
    Points
    199
    Par défaut
    J'ai essayé ce que tu m'as montré mais hélas scanbig2 me crée un fichier vide...

    voici ce que j'ai fait:

    ci-dessous, ne sachant pas trop j'ai initialisé d à nil

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
            c       := PChar(Page);
            d       := nil;
            k       := 1;
     
            Pb1.Position  := 0;
            Pb1.min       := 0;
            Pb1.Max       := length(Page);
     
            Taille        := 0;
     
            FD            := TFileStream.Create(ExtractFilePath(Application.ExeName)+cPathInput+'\'+cPathXml+'\'+MyCurrentDir+'\'+inttostr(k)+'.xml', fmCreate);
            Try
              while scanbig2('<patent-application-publication>', '</patent-application-publication>', c, d, long) do //notice) do
              begin
                FD.Write(d^, Long);
                Taille  := Taille + Long;
     
                if ((k mod 500)=0) then
                begin
                  FD.Free;
                  FD:=TFileStream.Create(ExtractFilePath(Application.ExeName)+cPathInput+'\'+cPathXml+'\'+MyCurrentDir+'\'+inttostr(k)+'.xml', fmCreate);
                end;
                inc(k);
     
                Pb1.position  := Taille;
              end;
            Finally
              FD.Free;
            End;
          End;
    et pour scanbig2, j'ai mis ch1 en commentaire lors de la déclaration, et mis en commentaire toutes les lignes
    où il y a TEXT.

    Je suppose que j'ai du oublié ou merdé quelque part...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    function ScanBig2(const Search1, Search2: string; var Ch, Ch1: PChar; var len: integer): Boolean;
    var
      //Ch1,
      Ch2: PChar;
    begin
      Result  :=False;
      if not Assigned(Ch) then
        Exit;
      Ch1 := StrPos(Ch, PChar(Search1));
      if Ch1 <> nil then
      begin
        Ch  := Ch1 + Length(Search1);
        Ch2 := StrPos(Ch, PChar(Search2));
        if Ch2 <> nil then
        begin
          //SetString(Text, Ch, Ch2 - Ch);
          Ch := Ch2 + Length(Search2);
        end
        else
        begin
          //Text := StrPas(Ch);
          Ch := nil;
        end;
        Result := True;
      end;
    end; {* func ScanBig *}

  8. #8
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 448
    Points
    28 448
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    function ScanBig2(const Search1, Search2: string; var Ch, Ch1: PChar; var len: integer): Boolean;
    var
      //Ch1,
      Ch2: PChar;
    begin
      Result  :=False;
      if not Assigned(Ch) then
        Exit;
      Ch1 := StrPos(Ch, PChar(Search1)); // ok Ch1 pointe donc sur le début de la balise ouvrante, c'est ce que l'on veux.
      if Ch1 <> nil then
      begin
        Ch  := Ch1 + Length(Search1); // Ch passe à la fin de la balise ouvrante
        Ch2 := StrPos(Ch, PChar(Search2)); // Ch2 pointe sur le début de la balise fermante
        if Ch2 <> nil then
        begin
          //SetString(Text, Ch, Ch2 - Ch);
          Ch := Ch2 + Length(Search2); // Ch pointe sur la fin de la balise fermante
        end
        else
        begin
          //Text := StrPas(Ch);
          Ch := nil; // fin
        end;
        Result := True; // ok et où est défini la valeur de len ? il nous faut Len = Ch - Ch1...sauf quand Ch = nil évidemment :)
      end;
    end; {* func ScanBig *}
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  9. #9
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    624
    Détails du profil
    Informations personnelles :
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 624
    Points : 199
    Points
    199
    Par défaut
    Salut Paul,

    Désolé je comptais y bosser cette après-midi ou demain matin et tu as déjà répondu...

    Effectivement, j'ai modifié suivant tes conseils le code de la fonction, cela fonctionne mais le temps de traitement
    est strictement identique hélas... aucun gain de perf.

    A moins que ce que j'ai ajouté, en fait juste, ne soit pas suffisant mais bon j'en doute:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    ...
        begin
          //Text := StrPas(Ch);
          Len := 0;
          Ch  := nil; // fin
        end;
        Len := Ch - Ch1;
        Result := True; // ok et où est défini la valeur de len ? il nous faut Len = Ch - Ch1...sauf quand Ch = nil évidemment :)
    ...

  10. #10
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 448
    Points
    28 448
    Par défaut
    ok, bon ça de toute façon c'était juste pas propre

    maintenant il faut ajouter des compteurs pour savoir ce qui prend du temps...et c'est la partie longue qu'il faudra optimiser....exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    var
      t1, t2: TDateTime;
    begin
      t1 := Now;
      Stream.LoadFromFile(...);
      t2 := Now;
      Memo1.Lines.Add('La lecture du ficher prend ' + IntToStr(MilisecondsBetween(t1, t2)) + 'ms');
    end;
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  11. #11
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    624
    Détails du profil
    Informations personnelles :
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 624
    Points : 199
    Points
    199
    Par défaut
    sans hésiter c'est la fonction scanbig2 qui prend environ une seconde, tout le reste est instantané ou alors ne prend que quelques secondes mais seulement une fois.

    c'est donc scanbig2 qui est trop long hélas....va falloir que je trouve totalement autre chose, tu penses pas ?

    Mon fichier test fait env. 700Mo pour env. 3500 notices

  12. #12
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    624
    Détails du profil
    Informations personnelles :
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 624
    Points : 199
    Points
    199
    Par défaut
    aujourd'hui je vais essayer xml_split en perl juste pour voir les temps de réponse. je reviendrai sur le post pour vous donner les valeurs

  13. #13
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 519
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 519
    Points : 25 037
    Points
    25 037
    Par défaut
    Regarde sur UltraEdit ou Notepad++ combien temps leur prend la recherche 1s pour 700Mo ce n'est pas si horrible
    Combien fois est appelé ScanBig ? une fois ou 3500 fois ?
    Si c'est une fois, ta fonction n'a pas à rougir de ses performances mais vu la boucle while je crains que ce ne soit pas le cas
    Donc je pense qu'elle est appelé 3500 fois donc 3500 secondes, oui c'est un peu long

    As-tu essayé deux appels de SearchBinaryInFile pour obtenir le tableau des <tag> et le tableau des </tag> ?
    Je n'ai pas de XML si gros, j'ai donc pris le fichier binaire "C:\Windows\SoftwareDistribution\DataStore\DataStore.edb" de 608 Mo et j'ai trouvé la chaine Unicode "Identity" pour 1052671 occurrences en 5072 ms et la chaine Unicode "SELECT" pour 40 occurrences en 5034 ms via SearchBinaryInFile ( la version d'origine a été écrite en D6, je ne crois pas qu'elle soit impacté par l'Unicode )
    Sur le forum, il existe aussi SearchStringInFile

    En extrapolant, cela mettra 6-7s pour trouver les offset des <tag> et 6-7s pour trouver </tag> donc 12-14s pour trouver les 3500 positions dans ton fichier de 700Mo
    Tu auras deux tableaux à parcourir pour avoir le début-fin de chaque XML
    Ensuite, cela repart su ton traitement avec un TFileStream où l'on écrit tout ce qu'il y entre <tag> et </tag>
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  14. #14
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    624
    Détails du profil
    Informations personnelles :
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 624
    Points : 199
    Points
    199
    Par défaut
    Non je n'ai pas essayé avec le SearchBinaryInFile, mais effectivement ça peut être une piste.

    Pour la recherche des balises via NotePad++ (TextPad aussi), sur un fichier de 764Mo, je recherche par exemple la chaîne:

    <application-reference appl-type="utility">

    c'est quasiment instantanée sur mon portable (Asus X750J).

    Je sais qu'1 seconde c'est pas trop mal, mais le hic c'est que j'ai en nombre de fichier:
    (52 * 16) + (52 * 46) = 3224 fichiers de 700Mo !

    et du coup, si on considère qu'en moyenne il y a 4000 notices par fichiers qui prend 1s, cela fait:

    4000 s / fichier * 3224 fichiers.....
    env. 1h05 / fichiers * 3224 !

    j'ai le temps de mourir

  15. #15
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 519
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 519
    Points : 25 037
    Points
    25 037
    Par défaut
    En code APPROXIMATIF
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
     
    var
      tagBegin, tagEnd: string;
      SearchBinary: TByteDynArray;
      OffSetsBegin, OffsetsEnd: TInt64DynArray;
      I: Integer;
      FSBig, FSSmall: TFileStream;
      S: string;
    begin
      tagBegin := '<patent-application-publication>';
      tagEnd := '</patent-application-publication>';
     
      SetLength(SearchBinary, Length(tagBegin)); // D7 donc AnsiChar
      Move(PChar(tagBegin)^, SearchBinary[0], Length(tagBegin));
     
      SearchBinaryInFile('C:\Big.xml' , SearchBinary, OffSetsBegin, True);
     
      SetLength(SearchBinary, Length(tagEnd)); // D7 donc AnsiChar
      Move(PChar(tagEnd)^, SearchBinary[0], Length(tagEnd));
     
      SearchBinaryInFile('C:\Big.xml' , SearchBinary, OffSetsEnd, True);
     
      if Length(OffSetsBegin) = Length(OffSetsEnd) then
      begin
     
        FSBig := TFileStream.Create('C:\Big.xml', fmOpenReadWrite);
        try
          for I := Low(OffSetsBegin) to High(OffSetsBegin) do
          begin
            FSBig.Seek(OffSetsBegin[I], soBeginning);
            SetLength(S, OffSetsEnd[I] - OffSetsBegin[I] + Length(tagEnd));
            FSBig.Read(PChar(S)^, Length(S));
     
            FSSmall := TFileStream.Create('C:\Small.' + IntToStr(I) + '.xml', fmCreate);
            try
              FSSmall.Write(PChar(S)^, Length(S));
            finally
              FSSmall.Free();
            end;
          end;
        finally
          FSBig.Free();
        end;
      end;
    end;
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  16. #16
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    624
    Détails du profil
    Informations personnelles :
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 624
    Points : 199
    Points
    199
    Par défaut
    Je vais tester ton code ShaiLeTroll, je reviens sur le post dès que j'ai des valeurs de temps !

    merci en tout cas à tous les 2

  17. #17
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 519
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 519
    Points : 25 037
    Points
    25 037
    Par défaut
    Je viens de le tester sur un fichier XML issu d'un XLSX décompressé par 7-zip, il fait 831 Mo, je l'ai renommé 'C:\Tmp\e'

    En utilisant SearchBinaryInFile, cela me trouve
    89251763 occurrences de la chaine '<' en 11251 ms, 44143925 occurrences de la chaine '</' en 9674 ms
    et 963912 occurrences de la chaine '/>' en 7304 ms dans ce fichier de 831 Mo
    même Notepad++ refuse de l'ouvrir car trop gros !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    var
      tagBegin, tagEnd: Ansistring;
      SearchBinary: TByteDynArray;
      OffSetsBegin, OffsetsEnd: TInt64DynArray;
      I: Integer;
      FSBig, FSSmall: TFileStream;
      S: Ansistring;
    begin
      tagBegin := '<';
      tagEnd := '>';
     
      SetLength(SearchBinary, Length(tagBegin) * SizeOf(AnsiChar));
      Move(PAnsiChar(tagBegin)^, SearchBinary[0], Length(SearchBinary));
     
      SearchBinaryInFile('C:\Tmp\e' , SearchBinary, OffSetsBegin);
     
      SetLength(SearchBinary, Length(tagEnd) * SizeOf(AnsiChar));
      Move(PAnsiChar(tagEnd)^, SearchBinary[0], Length(SearchBinary));
     
      SearchBinaryInFile('C:\Tmp\e' , SearchBinary, OffSetsEnd);
     
      if Length(OffSetsBegin) = Length(OffSetsEnd) then
      begin
     
        FSBig := TFileStream.Create('C:\Tmp\e', fmOpenReadWrite);
        try
          for I := Low(OffSetsBegin) to High(OffSetsBegin) do
          begin
            FSBig.Seek(OffSetsBegin[I], soBeginning);
            SetLength(S, OffSetsEnd[I] - OffSetsBegin[I] + Length(tagEnd));
            FSBig.Read(PAnsiChar(S)^, Length(S) * SizeOf(AnsiChar));
     
            FSSmall := TFileStream.Create('C:\Tmp\e.' + IntToStr(I) + '.split', fmCreate);
            try
              FSSmall.Write(PAnsiChar(S)^, Length(S) * SizeOf(AnsiChar));
            finally
              FSSmall.Free();
            end;
          end;
        finally
          FSBig.Free();
        end;
      end;
    end;
    Voici ce que donne les 3 premier fichiers découpé avec le code ci-dessus qui fonctionne sur XE2 et je pense compatible D7

    Code xml : Sélectionner tout - Visualiser dans une fenêtre à part
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    Code xml : Sélectionner tout - Visualiser dans une fenêtre à part
    <worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x14ac" xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac">
    Code xml : Sélectionner tout - Visualiser dans une fenêtre à part
    <dimension ref="A1:AC780876"/>
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  18. #18
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    624
    Détails du profil
    Informations personnelles :
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 624
    Points : 199
    Points
    199
    Par défaut
    heu comment dire...j'ai pas encore tout mis en place mais les premiers essais sont mega concluant !!!!!

    Pour un fichier de 400Mo, de plusieurs minutes je passe à.......3s !!!!!!! Incroyable !!!!

    J'affine la fonction scanbig3 (ajout du nombre de groups de fichiers) et je la rends dispo dans ce post !!!!

  19. #19
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    624
    Détails du profil
    Informations personnelles :
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 624
    Points : 199
    Points
    199
    Par défaut
    ben en fait y'a rien à affiner car entre 4000 et 5000 petits fichiers me convient tout à fait pour mon traitement !

    Merci ShaiLeTroll et Paul !!!!!

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Convertir de gros fichiers en binaire
    Par abbd dans le forum C#
    Réponses: 4
    Dernier message: 19/04/2012, 08h34
  2. Partir d'un gros fichier pour en faire plusieurs petits
    Par Bruno13 dans le forum Débuter
    Réponses: 12
    Dernier message: 07/10/2009, 13h12
  3. Concaténation de plusieurs gros fichiers
    Par tnarol dans le forum Programmation et administration système
    Réponses: 7
    Dernier message: 11/09/2009, 15h19
  4. [Fichier] Readfile, embed et "gros" fichiers
    Par jak0 dans le forum Langage
    Réponses: 5
    Dernier message: 19/01/2006, 12h19
  5. plusieurs pages pour gros fichiers (processeur js)
    Par arnobidul dans le forum XML/XSL et SOAP
    Réponses: 1
    Dernier message: 25/07/2005, 09h22

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo