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 :

Lire fichier texte large avec ProgressBar


Sujet :

Langage Delphi

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2012
    Messages
    23
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2012
    Messages : 23
    Points : 22
    Points
    22
    Par défaut Lire fichier texte large avec ProgressBar
    Bonjour,

    je souhait de lire et traiter le texte d'une fichier tres large (plusieurs Go). Naturellement, impossible de charger en mémoire avec le temps tres longue et avec erreur "out of memory".

    Je charge alors le fichier ligne par ligne et souhaitera mettre en place un ProgressBar. Neanmoins, sans savoir combien de lignes il y a, j'ai pensé de utiliser l'astuce suivant :

    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
    procedure LoadTextFile;
    Var
      FichTest: TextFile;
      Str1: String;
    begin
      ProgressBar1.Max := FileSize(MyFilename);
      ProgressBar1.Position := 0;
      AssignFile(FichTest, MyFilename);
      Reset(FichTest);
      while not Eof(FichTest) do
      Begin
        Readln(FichTest, Str1);
        ProgressBar1.Position := ProgressBar1.Position + ByteLength(Str1);
      End;
      CloseFile(FichTest);
    End;
    Neanmoins, le ProgressBar est complet longtemps avant la fin du fichier et atteint. Est ce qu'il y a une autre possibilité au lieu d'utiliser ?

  2. #2
    Expert confirmé
    Avatar de Ph. B.
    Homme Profil pro
    Freelance
    Inscrit en
    Avril 2002
    Messages
    1 784
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France, Haute Garonne (Midi Pyrénées)

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

    Informations forums :
    Inscription : Avril 2002
    Messages : 1 784
    Points : 5 915
    Points
    5 915
    Par défaut
    Bonjour,
    Citation Envoyé par DavKli Voir le message
    Neanmoins, le ProgressBar est complet longtemps avant la fin du fichier et atteint. Est ce qu'il y a une autre possibilité au lieu d'utiliser ByteLength ?
    Oui, en utilisant les commandes dédiées comme function FilePos(var f: File): Integer;.
    Cela donne :
    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
    procedure LoadTextFile;
    Var
      FichTest: TextFile;
      Str1: String;
    begin
      //ProgressBar1.Max := FileSize(MyFilename);
      ProgressBar1.Position := 0;
      AssignFile(FichTest, MyFilename);
      Reset(FichTest);
      ProgressBar1.Max := FileSize(FichTest);
      while not Eof(FichTest) do
      Begin
        Readln(FichTest, Str1);
        //ProgressBar1.Position := ProgressBar1.Position + ByteLength(Str1);
        ProgressBar1.Position := FilePos(FichTest);
      End;
      CloseFile(FichTest);
    end;
    Philippe.

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2012
    Messages
    23
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2012
    Messages : 23
    Points : 22
    Points
    22
    Par défaut Lire fichier texte large avec ProgressBar
    Bonjour,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ProgressBar1.Max := FileSize(FichTest);
    n'xiste pas vu que FichTest est du Type TextFile et produire erreur E2010 Types incompatible. Je peut bien avoir la taille du fichier avec

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ProgressBar1.Max := FileSize(FilePath);
    mais cela ne donnera rien avec

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ProgressBar1.Position := FilePos(FichTest)
    Avec ce derniere, la fiche est chargé completement avec la ProgressBar quasiment vide.

  4. #4
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 426
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    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 426
    Points : 24 790
    Points
    24 790
    Par défaut
    Regarde ce vieux sujet Fichier CSV, Compteur de lignes

    Idem, tu fais le GetFileSize en variante 64Bits (pour dépasser les 2Go)
    Puis tu compte toi même la taille lu !
    Facile c'est la longueur de ta chaine + CRLF

    Pense à faire un ProgressBar.Refresh(); toutes les 1000 lignes par exemple pour forcer le dessin du ProgressBar
    Plus lourd, la Application.ProcessMessages pour éviter que Windows pense que l'application est bloqué, idem ne pas en abuser, une fois toute les 1000 lignes

    Tu peux aussi utiliser le TTextFileReader dont voici une version compatible XE2 mais pas encore Unicode

    Dans ton cas, tu vas créer un TFileStream sur ton fichier, le Stream te donnera la taille et la position
    Tu passe ce Stream en paramètre du constructeur de TTextFileReader (il sera TextStream)
    Tu peux aussi laisser la gestion du fichier au TTextFileReader qui se chargera de créer le Stream en interne

    Il te suffit de boucler EOF et ReadNextLine


    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
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    418
    419
    420
    421
    422
    423
    424
    425
    426
    427
    428
    429
    430
    431
    432
    433
    434
    435
    436
    437
    438
    439
    440
    441
    442
    443
    444
    445
    446
    447
    448
    449
    450
    451
    452
    453
    454
    455
    456
    457
    458
    459
    460
    461
    462
    463
    464
    465
    466
    467
    468
    469
    470
    471
    472
    473
    474
    475
    476
    477
    478
    479
    480
    481
    482
    483
    484
    485
    486
    487
    488
    489
    490
    491
    492
    493
    494
    495
    496
    497
    498
    499
    500
    501
    502
    503
    504
    505
    506
    507
    508
    509
    510
    511
    512
    513
    514
    515
    516
    517
    518
    519
    520
    521
    522
    523
    524
    525
    526
    527
    528
    529
    530
    531
    532
    533
    534
    535
    536
    537
    538
    539
    540
    541
    542
    543
    544
    545
    546
    547
    548
    549
    550
    551
    552
    553
    554
    555
    556
    557
    558
    559
    560
    561
    562
    563
    564
    565
    566
    567
    568
    569
    570
    571
    572
    573
    574
    575
    576
    577
    578
    579
    580
    581
    582
    583
    584
    585
    586
    587
    588
    589
    590
    591
    592
    593
    594
    595
    596
    597
    598
    599
    600
    601
    602
    603
    604
    605
    606
    607
    608
    609
    610
    611
    612
    613
    614
    615
    616
    617
    618
    619
    620
    621
    622
    623
    624
    625
    626
    627
    628
    629
    630
    631
    632
    633
    634
    635
    636
    637
    638
    639
    640
    641
    642
    643
    644
    645
    646
    647
    648
    649
    650
    651
    652
    653
    654
    655
    656
    657
    658
    659
    660
    661
    662
    663
    664
    665
    666
    667
    668
    669
    670
    671
    672
    673
    674
    675
    676
    677
    678
    679
    680
    681
    682
    683
    684
    685
    686
    687
    688
    689
    690
    691
    692
    693
    694
    695
    696
    697
    698
    699
    700
    701
    702
    703
    704
    705
    706
    707
    708
    709
    710
    711
    712
    713
    714
    715
    716
    717
    718
    719
    720
    721
    722
    723
    724
    725
    726
    727
    728
    729
    730
    731
    732
    733
    734
    735
    736
    737
    738
    739
    740
    741
    742
    743
    744
    //------------------------------------------------------------------------------
    (*                SoLuTions is an Versatile Library for Delphi                 -
     *                                                                             -
     *  Version alternative publiée sur "www.developpez.net"                       -
     *  Post : "[D7][StringGrid] Très gros fichiers à parser (comment faire un streaming?)"
     *  Post Number : 2292692                                                      -
     *  Post URL = "http://www.developpez.net/forums/d374632/environnements-developpement/delphi/composants-vcl/d7-stringgrid-tres-gros-fichiers-parser-faire-streaming/#post2292692"
     *                                                                             -
     *  Version alternative publiée sur "www.developpez.net"                       -
     *  Post : "Fichier CSV, Compteur de lignes"                                   -
     *  Post Number : 2419880                                                      -
     *  Post URL = "http://www.developpez.net/forums/d394452/environnements-developpement/delphi/langage/fichier-csv-compteur-lignes/#post2419880"
     *                                                                             -
     *  Copyright ou © ou Copr. "SLT Solutions", (2006)                            -
     *  contributeur : ShaiLeTroll (2007) - Passage en Classe d'un code procédural -
     *  contributeur : ShaiLeTroll (2011) - Préparation au passage Ansi vers Unicode sous C++Builder XE2 (code en Delphi XE2 mais utilisé par projet C++Builder XE2)
     *  contributeur : ShaiLeTroll (2012) - Renommage Fichier et Correction XE2    -
     *  contributeur : ShaiLeTroll (2012) - Documentation Insight                  -
     *                                                                             -
     * ShaiLeTroll@gmail.com                                                       -
     *                                                                             -
     * Ce logiciel est un programme informatique servant à aider les développeurs  -
     * Delphi avec une bibliothèque polyvalente, adaptable et fragmentable.        -
     *                                                                             -
     * Ce logiciel est régi par la licence CeCILL-C soumise au droit français et   -
     * respectant les principes de diffusion des logiciels libres. Vous pouvez     -
     * utiliser, modifier et/ou redistribuer ce programme sous les conditions      -
     * de la licence CeCILL-C telle que diffusée par le CEA, le CNRS et l'INRIA    -
     * sur le site "http://www.cecill.info".                                       -
     *                                                                             -
     * En contrepartie de l'accessibilité au code source et des droits de copie,   -
     * de modification et de redistribution accordés par cette licence, il n'est   -
     * offert aux utilisateurs qu'une garantie limitée.  Pour les mêmes raisons,   -
     * seule une responsabilité restreinte pèse sur l'auteur du programme,  le     -
     * titulaire des droits patrimoniaux et les concédants successifs.             -
     *                                                                             -
     * A cet égard  l'attention de l'utilisateur est attirée sur les risques       -
     * associés au chargement,  à l'utilisation,  à la modification et/ou au       -
     * développement et à la reproduction du logiciel par l'utilisateur étant      -
     * donné sa spécificité de logiciel libre, qui peut le rendre complexe à       -
     * manipuler et qui le réserve donc à des développeurs et des professionnels   -
     * avertis possédant  des  connaissances  informatiques approfondies.  Les     -
     * utilisateurs sont donc invités à charger  et  tester  l'adéquation  du      -
     * logiciel à leurs besoins dans des conditions permettant d'assurer la        -
     * sécurité de leurs systèmes et ou de leurs données et, plus généralement,    -
     * à l'utiliser et l'exploiter dans les mêmes conditions de sécurité.          -
     *                                                                             -
     * Le fait que vous puissiez accéder à cet en-tête signifie que vous avez      -
     * pris connaissance de la licence CeCILL-C, et que vous en avez accepté les   -
     * termes.                                                                     -
     *                                                                             -
     *----------------------------------------------------------------------------*)
    unit SLT.Common.TextFileReader;
     
    interface
     
    uses System.SysUtils, System.Classes;
     
    type
      { Forward class declarations }
      TSLTTextFileReader = class;
      ISLTTextStreamReader = interface;
      TSLTTextStreamReaderAnsi = class;
     
      PTextFileReaderIndex = ^TSLTTextFileReaderIndex;
      TSLTTextFileReaderIndex = packed record
        OffSet: Int64;
        Length: Integer; // une Chaine Delphi ne peut pas dépasser cette taille
      end;
     
      TSLTTextFileReaderBuildIndexProgress = procedure(Sender: TObject; const Position, Size: Int64; var Aborting: Boolean) of object;
     
      /// <summary>Erreur de lecture du fichier d'index associé à un fichier texte</summary>
      ETextFileReaderErrorIndex = class(Exception);
      /// <summary>Erreur de lecture d'un fichier texte</summary>
      ETextFileReaderError = class(Exception);
     
      /// <summary>Classe permettant de lire et d'indexer un fichier texte</summary>
      TSLTTextFileReader = class(TObject)
      private
        // Membres privés
        FTextStream: TStream;
        FOwnsTextStream: Boolean;
        FFileName: TFileName;
        FIndexName: TFileName;
        FWorkingSuffix: string;
        FWorkingPath : TFileName;
        FWorkingPathIsTemp : Boolean;
        FIndexFile: TFileStream; // un File of aurait été plus pratique mais limité à 2Go, donc environ 178 millions de lignes, hors un fichier texte de 4Go, peut en contenir bien plus ...
        FIndexed: Boolean;
        FAutoIndexed: Boolean;
        FIndexCount: Int64;
        FIndexRecSize: Byte;
        FStreamReader: ISLTTextStreamReader;
        FUseCROnly: Boolean;
        FOnBuildIndexProgress: TSLTTextFileReaderBuildIndexProgress;
        FDeleteIndexOnFree: Boolean;
        FAllowUseExistingIndexFile: Boolean;
     
        // Méthodes privés
        function GetIndexed: Boolean;
        procedure SetIndexed(const Value: Boolean);
        function GetCount: Int64;
        function GetEOF: Boolean;
        function ReadLineFromIndexRec(const IndexRec: TSLTTextFileReaderIndex): string;
        function ReadIndex(const Index: Int64): TSLTTextFileReaderIndex;
        function ReadLineRaw(const Index: Int64; const OffSet: Int64 = 0): string;
        procedure BuildLinesIndexes();
        procedure BuildIndexProgressEventHandler(Sender: TObject; const Position, Size: Int64; var Aborting: Boolean);
        function GetIndexFileName(): TFileName;
        function GetLinearPosition(): Int64;
      public
        // Constructeurs
        constructor Create(const AFileName: string; AEncoding: TEncoding; AAutoIndexed: Boolean = True; AAllowUseExistingIndexFile: Boolean = False); overload;
        constructor Create(ATextStream: TStream; AEncoding: TEncoding; AAutoIndexed: Boolean = True; AAllowUseExistingIndexFile: Boolean = False); overload;
        destructor Destroy; override;
     
        // Méthodes
        class function BuildLinesIndexesFor(const AFileName: string; AEncoding: TEncoding): TFileName;
     
        // Méthodes
        function ReadLine(const Index: Int64): string;
        procedure ReadLines(const IndexBegin, IndexEnd: Int64; Lines: TStrings; DoClear: Boolean = True);
        function ReadNextLine(): string;
        procedure ReadNextLines(const ACount: Word; Lines: TStrings; DoClear: Boolean = True);  // Il semble raisonnable de limiter la lecture par TStrings à 65535
        procedure DeleteLine(const Index: Int64); // Opération Lente
        procedure DeleteLines(const IndexBegin, IndexEnd: Int64); // Opération Lente
     
        // Propriétés
        property Count: Int64 read GetCount;
        property EOF: Boolean read GetEOF;
        property TextStream: TStream read FTextStream;
        property OwnsTextStream: Boolean read FOwnsTextStream write FOwnsTextStream;
        property FileName: TFileName read FFileName;
        property IndexName: TFileName read FIndexName;
        property WorkingSuffix: string read FWorkingSuffix;
        property WorkingPath: TFileName read FWorkingPath;
        property Indexed: Boolean read GetIndexed write SetIndexed; // pour mettre la valeur à True, il faut que le fichier existe, ou alors que AutoIndexed soit à true
        property AutoIndexed: Boolean read FAutoIndexed write FAutoIndexed; // Si l'on change la propriété Indexed, cela génère le fichier automatiquement
        property Lines[const Index: Int64]: string read ReadLine;
        property LinearPosition: Int64 read GetLinearPosition;
        property UseCROnly: Boolean read FUseCROnly write FUseCROnly;
        property OnBuildIndexProgress: TSLTTextFileReaderBuildIndexProgress read FOnBuildIndexProgress write FOnBuildIndexProgress;
        property DeleteIndexOnFree: Boolean read FDeleteIndexOnFree write FDeleteIndexOnFree;
        property AllowUseExistingIndexFile: Boolean read FAllowUseExistingIndexFile write FAllowUseExistingIndexFile; // Par prudence, un fichier index doit être créé pour garantir son adéquation avec le fichier lu
      end;
     
      ISLTTextStreamReader = interface
        ['{2E0ABC26-A69D-46C5-A8DF-FA7D544C972E}']
     
        // Méthodes
        function ReadLineFromIndexRec(const IndexRec: TSLTTextFileReaderIndex): string;
        function ReadLineRaw(AIndexFile: TFileStream; AUseCROnly: Boolean; const Index: Int64; const OffSet: Int64 = 0): string;
        procedure BuildLinesIndexes(AIndexFile: TFileStream; AUseCROnly: Boolean);
     
        // Accesseurs
        function GetTextStream(): TStream;
        procedure SetTextStream(const Value: TStream);
        function GetTextSize(): Int64;
        function GetLinearPosition(): Int64;
        procedure SetLinearPosition(const Value: Int64);
        function GetOnBuildIndexProgress(): TSLTTextFileReaderBuildIndexProgress;
        procedure SetOnBuildIndexProgress(const Value: TSLTTextFileReaderBuildIndexProgress);
     
        // Propriétés
        property TextStream: TStream read GetTextStream write SetTextStream;
        property TextSize: Int64 read GetTextSize;
        property LinearPosition: Int64 read GetLinearPosition write SetLinearPosition;
        property OnBuildIndexProgress: TSLTTextFileReaderBuildIndexProgress read GetOnBuildIndexProgress write SetOnBuildIndexProgress;
      end;
     
      TSLTTextStreamReaderAnsi = class(TInterfacedObject, ISLTTextStreamReader)
      private
        // Membres privés
        FTextStream: TStream;
        FTextSize: Int64;
        FLinearPosition: Int64;
        FOnBuildIndexProgress: TSLTTextFileReaderBuildIndexProgress;
     
        // Méthodes privés
        function DoBuildIndexProgress(const Position, Size: Int64): Boolean;
      public
        // Méthodes - Implémentation de ISLTTextStreamReader
        function ReadLineFromIndexRec(const IndexRec: TSLTTextFileReaderIndex): string;
        function ReadLineRaw(AIndexFile: TFileStream; AUseCROnly: Boolean; const Index: Int64; const OffSet: Int64 = 0): string;
        procedure BuildLinesIndexes(AIndexFile: TFileStream; AUseCROnly: Boolean);
     
        // Accesseurs - Implémentation de ISLTTextStreamReader
        function GetTextStream(): TStream;
        procedure SetTextStream(const Value: TStream);
        function GetTextSize(): Int64;
        function GetLinearPosition(): Int64;
        procedure SetLinearPosition(const Value: Int64);
        function GetOnBuildIndexProgress(): TSLTTextFileReaderBuildIndexProgress;
        procedure SetOnBuildIndexProgress(const Value: TSLTTextFileReaderBuildIndexProgress);
      end;
     
     
    implementation
     
    uses
    {$IFDEF MSWINDOWS}
      Winapi.Windows,
    {$ELSE MSWINDOWS}
    {$MESSAGE ERROR 'Implémentation uniquement Windows pour TSLTTextFileReader'}
    {$ENDIF MSWINDOWS}
      System.IOUtils,
      SLT.Common.FileUtilsEx;
     
    resourcestring
      SEncodingNotSupported = 'Encodage non géré : %s';
      SIndexNotExist = 'Le Fichier d''Index n''existe pas !';
      STooMuchRead = 'Le Nombre Maximal de la Lecture par lot doit inférieur ou égale à %d au lieu de %d';
      STooMuchDelete = 'Le Nombre Maximal de la Suppression par lot doit être inférieur ou égale à %d au lieu de %d';
      SNoIndexedDelete = 'La Suppression n''est possible qu''avec un Fichier Indexé';
     
    { TSLTTextFileReader }
     
    { TSLTTextFileReader - Constructeurs }
     
    //------------------------------------------------------------------------------
    constructor TSLTTextFileReader.Create(const AFileName: string; AEncoding: TEncoding; AAutoIndexed: Boolean = True; AAllowUseExistingIndexFile: Boolean = False);
    begin
      FFileName := AFileName;
     
      FTextStream := TFileStream.Create(FileName, fmOpenRead, fmShareDenyWrite);
      FOwnsTextStream := True;
     
      Create(FTextStream, AEncoding, AAutoIndexed, AAllowUseExistingIndexFile);
    end;
     
    //------------------------------------------------------------------------------
    constructor TSLTTextFileReader.Create(ATextStream: TStream; AEncoding: TEncoding; AAutoIndexed: Boolean = True; AAllowUseExistingIndexFile: Boolean = False);
    begin
      inherited Create();
     
      FIndexCount := -1;
      FIndexRecSize := SizeOf(TSLTTextFileReaderIndex);
     
      if AEncoding = TEncoding.ANSI then
        FStreamReader := TSLTTextStreamReaderAnsi.Create()
      else
        raise ETextFileReaderError.CreateResFmt(@SEncodingNotSupported, [AEncoding.EncodingName]);
     
      FTextStream := ATextStream;
      FIndexFile := nil;
      FStreamReader.TextStream := FTextStream;
      FStreamReader.LinearPosition := 0;
      FStreamReader.OnBuildIndexProgress := BuildIndexProgressEventHandler;
     
      Indexed := False;
      AutoIndexed := AAutoIndexed;
      AllowUseExistingIndexFile := AAllowUseExistingIndexFile;
    end;
     
    //------------------------------------------------------------------------------
    destructor TSLTTextFileReader.Destroy();
    var
      Dir: TFileName;
    begin
      FreeAndNil(FIndexFile);
     
      if Assigned(FStreamReader) then
        FStreamReader.TextStream := nil;
     
      if FOwnsTextStream and Assigned(FTextStream) then
        FreeAndNil(FTextStream);
     
      if FDeleteIndexOnFree then
      begin
        // Nettoyage du fichier d'indexe
        if System.SysUtils.FileExists(FIndexName) then
          System.SysUtils.DeleteFile(FIndexName);
     
        // Nettoyage du dossier temporaire si celui est vide
        if FWorkingPathIsTemp then
        begin
          Dir := ExcludeTrailingPathDelimiter(FWorkingPath);
          RemoveDir(Dir);
          RemoveDir(ExtractFileDir(Dir));
        end;
      end;
     
      inherited;
    end;
     
    { TSLTTextFileReader - Méthodes Publiques }
     
    //------------------------------------------------------------------------------
    procedure TSLTTextFileReader.BuildIndexProgressEventHandler(Sender: TObject; const Position, Size: Int64; var Aborting: Boolean);
    begin
      if Assigned(FOnBuildIndexProgress) then
        FOnBuildIndexProgress(Sender, Position, Size, Aborting);
    end;
     
    //------------------------------------------------------------------------------
    procedure TSLTTextFileReader.BuildLinesIndexes();
    begin
      FIndexFile := TFileStream.Create(GetIndexFileName(), fmCreate, fmShareExclusive);
      try
        FStreamReader.BuildLinesIndexes(FIndexFile, FUseCROnly);
      finally
        FIndexFile.Free();
        FIndexFile := nil;
      end;
    end;
     
    //------------------------------------------------------------------------------
    class function TSLTTextFileReader.BuildLinesIndexesFor(const AFileName: string; AEncoding: TEncoding): TFileName;
    begin
      with TSLTTextFileReader.Create(AFileName, AEncoding, True, False) do
      try
        DeleteIndexOnFree := False;
        BuildLinesIndexes();
        Result := FIndexName;
      finally
        Free();
      end;
    end;
     
    //------------------------------------------------------------------------------
    function TSLTTextFileReader.ReadLine(const Index: Int64): string;
    begin
      if FIndexed then
        Result := ReadLineFromIndexRec(ReadIndex(Index))
      else
        Result := ReadLineRaw(Index);
    end;
     
    //------------------------------------------------------------------------------
    procedure TSLTTextFileReader.ReadLines(const IndexBegin, IndexEnd: Int64; Lines: TStrings; DoClear: Boolean = True);
    var
      Index: Word; // le For Delphi 6 ne gère pas le Int64, et il ne serait pas raisonnable de lire autant
      IndexCount: Int64;
      IndexMax: Int64;
    begin
      if Assigned(Lines) then
      begin
        if DoClear then
          Lines.Clear();
     
        if IndexEnd < Count then
          IndexMax := IndexEnd
        else
          IndexMax := Count - 1;
     
        IndexCount := IndexMax - IndexBegin;
        if (0 <= IndexCount) and (IndexCount <= High(Word)) then
        begin
          Lines.Capacity := Lines.Count + IndexCount;
          for Index := 0 to IndexMax - IndexBegin do
            Lines.Add(ReadLine(IndexBegin + Index));
        end else
        begin
          raise ETextFileReaderError.CreateResFmt(@STooMuchRead, [High(Word), IndexCount]);
        end;
      end;
    end;
     
    //------------------------------------------------------------------------------
    function TSLTTextFileReader.ReadNextLine: string;
    begin
      // Lecture d'une ligne depuis la position en cours
      Result := ReadLineRaw(0, FStreamReader.LinearPosition);
    end;
     
    //------------------------------------------------------------------------------
    procedure TSLTTextFileReader.ReadNextLines(const ACount: Word; Lines: TStrings; DoClear: Boolean = True);
    var
      Index: Word; // le For Delphi 6 ne gère pas le Int64, et il ne serait pas raisonnable de lire autant
    begin
      if Assigned(Lines) then
      begin
        if DoClear then
          Lines.Clear();
     
        Lines.Capacity := ACount;
        for Index := ACount - 1 downto 0 do
          Lines.Add(ReadNextLine());
      end;
    end;
     
    //------------------------------------------------------------------------------
    procedure TSLTTextFileReader.DeleteLine(const Index: Int64);
    begin
      if Indexed then
      begin
        // Je n'ai jamais eu le courage de le faire !
      end else
      begin
        raise ETextFileReaderError.Create(SNoIndexedDelete);
      end;
    end;
     
    //------------------------------------------------------------------------------
    procedure TSLTTextFileReader.DeleteLines(const IndexBegin, IndexEnd: Int64);
    var
      Index: Cardinal; // le For Delphi 6 ne gère pas le Int64, mais la suppression de 4 Millards de Lignes cela suffit
      ACount: Int64;
    begin
      ACount := IndexEnd - IndexBegin;
      if (0 <= ACount) and (ACount <= High(Word)) then
      begin
        for Index := IndexBegin to IndexEnd do
          DeleteLine(Index);
      end else
      begin
        raise ETextFileReaderError.CreateResFmt(@STooMuchDelete, [High(Cardinal), ACount]);
      end;
    end;
     
    { TSLTTextFileReader - Méthodes d'Accès }
     
    //------------------------------------------------------------------------------
    function TSLTTextFileReader.GetIndexed: Boolean;
    begin
      Result := FIndexed and Assigned(FIndexFile);
    end;
     
    //------------------------------------------------------------------------------
    function TSLTTextFileReader.GetIndexFileName(): TFileName;
    var
      lFileName: TFileName;
    begin
      if FFileName = '' then
      begin
        FWorkingPathIsTemp := True;
    {$IFDEF MSWINDOWS}
        FWorkingPath := GetTemporaryPathForProcess(FWorkingSuffix);
    {$ELSE MSWINDOWS}
        FWorkingPath := GetTemporaryPathWithSuffix(FWorkingSuffix);
    {$ENDIF MSWINDOWS}
        lFileName := 'SLTTFR_' + UIntToStr(NativeUInt(FTextStream)) + '.idx';
     
        // Si l'on peut créer le répertoire, on l'utilise comme dossier de travail
        // Sinon, on tente dans le repertoire en cours du processus (avec tous les effets de bords possibles)
        if SimpleForceDirectories(FWorkingPath) then
          Result := FWorkingPath + lFileName
        else
          Result := lFileName;
      end
      else
      begin
        FWorkingPathIsTemp := False;
        FWorkingPath := ExtractFilePath(FFileName);
        Result := FFileName + '.idx';
      end;
    end;
     
    //------------------------------------------------------------------------------
    function TSLTTextFileReader.GetLinearPosition(): Int64;
    begin
      Result := FStreamReader.LinearPosition;
    end;
     
    //------------------------------------------------------------------------------
    procedure TSLTTextFileReader.SetIndexed(const Value: Boolean);
    begin
      if FIndexed <> Value then
      begin
        if Assigned(FIndexFile) then
        begin
          FIndexFile.Free();
          FIndexFile := nil;
        end;
     
        FIndexed := Value;
        FIndexCount := 0;
     
        if FIndexed then
        begin
          if not AllowUseExistingIndexFile or not FileExists(FIndexName) then
            if AutoIndexed then
              BuildLinesIndexes()
            else
              raise ETextFileReaderErrorIndex.CreateRes(@SIndexNotExist);
     
          FIndexFile := TFileStream.Create(GetIndexFileName(), fmOpenRead, fmShareDenyWrite);
          FIndexCount := FIndexFile.Size div FIndexRecSize;
        end;
      end;
    end;
     
    //------------------------------------------------------------------------------
    function TSLTTextFileReader.GetCount: Int64;
    begin
      Result := FIndexCount;
    end;
     
    //------------------------------------------------------------------------------
    function TSLTTextFileReader.GetEOF: Boolean;
    begin
      Result := FStreamReader.LinearPosition >= FStreamReader.TextSize;
    end;
     
    { TSLTTextFileReader - Méthodes Privées }
     
    //------------------------------------------------------------------------------
    function TSLTTextFileReader.ReadIndex(const Index: Int64): TSLTTextFileReaderIndex;
    begin
      if Indexed and (Index < FIndexCount) then
      begin
        FIndexFile.Seek(Index * FIndexRecSize, soFromBeginning);
        FIndexFile.Read(Result, FIndexRecSize);
      end else
        ZeroMemory(@Result, FIndexRecSize); // Windows uniquement
    end;
     
    //------------------------------------------------------------------------------
    function TSLTTextFileReader.ReadLineFromIndexRec(const IndexRec: TSLTTextFileReaderIndex): string;
    begin
      Result := FStreamReader.ReadLineFromIndexRec(IndexRec);
    end;
     
    //------------------------------------------------------------------------------
    function TSLTTextFileReader.ReadLineRaw(const Index: Int64; const OffSet: Int64 = 0): string;
    begin
      Result := FStreamReader.ReadLineRaw(FIndexFile, FUseCROnly, Index, OffSet);
    end;
     
    { TSLTTextStreamReaderAnsi }
     
    //------------------------------------------------------------------------------
    procedure TSLTTextStreamReaderAnsi.BuildLinesIndexes(AIndexFile: TFileStream; AUseCROnly: Boolean);
    const
      BUF_SIZE = 1024;
      REC_BUF_SIZE = 65536;
      LF: Byte = 10;
      CR: Byte = 13;
    var
      TextBuf: array[0..BUF_SIZE-1] of Byte;
      IndexRec: PTextFileReaderIndex;
      IndexesRec: packed array[0..REC_BUF_SIZE-1] of TSLTTextFileReaderIndex;
      iBuf, Readed: Integer;
      AByte: Byte;
      LastIsCR: Boolean;
      iRec, MaxRec: Integer;
      IRSize: Integer;
      EndOfLine: Byte;
    begin
      // Positionnement au début du Fichier
      FTextStream.Seek(0, soFromBeginning);
      // Compteur/Index/Drapeau à Zéro
      iRec := 0;
      MaxRec := REC_BUF_SIZE - 1;
      IRSize := REC_BUF_SIZE * SizeOf(IndexRec^);
      ZeroMemory(@IndexesRec, IRSize); // Windows Uniquement
      IndexRec := @IndexesRec[iRec];
      LastIsCR := False;
      if AUseCROnly then
        EndOfLine := CR // Compatible MacOS avec CR isolé
      else
        EndOfLine := LF; // Compatible Windows couple CR LF et Linux LF
     
      // Boucle jusqu'à la fin
      while (FTextStream.Position < FTextSize) do
      begin
        if not DoBuildIndexProgress(FTextStream.Position, FTextSize) then
          Abort;
     
        Readed := FTextStream.Read(TextBuf, BUF_SIZE);
        for iBuf := 0 to Readed - 1 do
        begin
          AByte := TextBuf[iBuf];
          if (AByte = EndOfLine) then
          begin
            IndexRec^.Length := (FTextStream.Position - Readed + iBuf) - IndexRec^.OffSet;
            if not AUseCROnly and LastIsCR then
              Dec(IndexRec^.Length); // -1 car on inclu pas le CR dans un couple CR LF
     
            if iRec = MaxRec then
            begin
              AIndexFile.Write(IndexesRec, IRSize);
              iRec := 0;
            end else
              Inc(iRec);
     
            IndexRec := @IndexesRec[iRec];
            IndexRec^.OffSet := FTextStream.Position - Readed + iBuf + 1; // + 1 car on inclu pas le LF du couple CR LF ou le CR isolé
          end;
     
          if not AUseCROnly then
            LastIsCR := (AByte = CR);
        end;
      end;
      if IndexRec^.OffSet < FTextSize then
      begin
        IndexRec^.Length := FTextStream.Position - IndexRec^.OffSet;
        if iRec = MaxRec then
        begin
          AIndexFile.Write(IndexesRec, IRSize);
          iRec := 0;
        end else
          Inc(iRec);
      end;
     
      if iRec > 0 then
        AIndexFile.Write(IndexesRec, iRec * SizeOf(IndexRec^));
    end;
     
    //------------------------------------------------------------------------------
    function TSLTTextStreamReaderAnsi.DoBuildIndexProgress(const Position, Size: Int64): Boolean;
    begin
      if Assigned(FOnBuildIndexProgress) then
      begin
        Result := False;
        FOnBuildIndexProgress(Self, Position, Size, Result);
        Result := not Result; // la fonctionne renvoie True si on continue
      end
      else
        Result := True;
    end;
     
    //------------------------------------------------------------------------------
    function TSLTTextStreamReaderAnsi.GetLinearPosition: Int64;
    begin
      Result := FLinearPosition;
    end;
     
    //------------------------------------------------------------------------------
    function TSLTTextStreamReaderAnsi.GetOnBuildIndexProgress: TSLTTextFileReaderBuildIndexProgress;
    begin
      Result := FOnBuildIndexProgress;
    end;
     
    //------------------------------------------------------------------------------
    function TSLTTextStreamReaderAnsi.GetTextStream(): TStream;
    begin
      Result := FTextStream;
    end;
     
    //------------------------------------------------------------------------------
    function TSLTTextStreamReaderAnsi.GetTextSize: Int64;
    begin
      Result := FTextSize;
    end;
     
    //------------------------------------------------------------------------------
    function TSLTTextStreamReaderAnsi.ReadLineFromIndexRec(const IndexRec: TSLTTextFileReaderIndex): string;
    var
      ResultAnsi: AnsiString;
    begin
      if (IndexRec.OffSet >= 0) and (IndexRec.Length > 0) and (IndexRec.OffSet + IndexRec.Length <= FTextSize)then
      begin
        SetLength(ResultAnsi, IndexRec.Length);
        FTextStream.Seek(IndexRec.OffSet, soFromBeginning);
        FTextStream.Read(ResultAnsi[1], IndexRec.Length);
        Result := string(ResultAnsi); // Transtypage de chaîne explicite de AnsiString en string (UnicodeString)
      end else
        Result := '';
    end;
     
    //------------------------------------------------------------------------------
    function TSLTTextStreamReaderAnsi.ReadLineRaw(AIndexFile: TFileStream; AUseCROnly: Boolean; const Index, OffSet: Int64): string;
    const
      BUF_SIZE = 1024;
      LF: Byte = 10;
      CR: Byte = 13;
    var
      TextBuf: array[0..BUF_SIZE-1] of Byte;
      IndexRec: TSLTTextFileReaderIndex;
      iBuf, Readed: Integer;
      AByte: Byte;
      LastIsCR: Boolean;
      LineReaded: Int64;
      EndOfLine: Byte;
    begin
      // Positionnement au début du Fichier ou sur le Curseur de lecture linéaire
      FTextStream.Seek(OffSet, soFromBeginning);
     
      // Compteur/Index/Drapeau à Zéro
      IndexRec.OffSet := OffSet;
      IndexRec.Length := 0;
      LastIsCR := False;
      if AUseCROnly then
        EndOfLine := CR // Compatible MacOS avec CR isolé
      else
        EndOfLine := LF; // Compatible Windows couple CR LF et Linux LF
      LineReaded := 0;
      // Boucle jusqu'à la fin
      while (FTextStream.Position < FTextSize) do
      begin
        Readed := FTextStream.Read(TextBuf, BUF_SIZE);
        for iBuf := 0 to Readed - 1 do
        begin
          AByte := TextBuf[iBuf];
          if (AByte = EndOfLine) then
          begin
            FLinearPosition := FTextStream.Position - Readed + iBuf;
            IndexRec.Length := FLinearPosition - IndexRec.OffSet;
            Inc(FLinearPosition); // car on n'inclu pas la fin de ligne dans la prochaine ligne
            if not AUseCROnly and LastIsCR then
              Dec(IndexRec.Length); // -1 car on inclu pas le CR dans un couple CR LF
     
            // Si l'on trouve la fin de ligne, on récupère directement les données
            if (LineReaded = Index) then
            begin
              Result := ReadLineFromIndexRec(IndexRec);
              Exit;
            end;
            // la prochaine ligne commencera après ce dernier séparateur de ligne
            IndexRec.OffSet := FLinearPosition;
            Inc(LineReaded);
          end;
          if not AUseCROnly then
            LastIsCR := (AByte = CR);
        end;
      end;
      // On a pas trouvé de fin de ligne, il est fort possible que ce soit la dernière sans fin de ligne
      // On récupère l'ensemble de la fin du fichier, on lit (Fin - Offset) Byte à partir de Offset
      if IndexRec.OffSet < FTextSize then
      begin
        IndexRec.Length := FTextStream.Position - IndexRec.OffSet;
        FLinearPosition := FTextStream.Position + 1; // + 1 ainsi on sera définitivment en dehors !
        if (LineReaded = Index) then
        begin
          Result := ReadLineFromIndexRec(IndexRec);
          Exit;
        end;
      end;
      Result := '';
    end;
     
    //------------------------------------------------------------------------------
    procedure TSLTTextStreamReaderAnsi.SetLinearPosition(const Value: Int64);
    begin
      FLinearPosition := Value;
    end;
     
    //------------------------------------------------------------------------------
    procedure TSLTTextStreamReaderAnsi.SetOnBuildIndexProgress(const Value: TSLTTextFileReaderBuildIndexProgress);
    begin
      FOnBuildIndexProgress := Value;
    end;
     
    //------------------------------------------------------------------------------
    procedure TSLTTextStreamReaderAnsi.SetTextStream(const Value: TStream);
    begin
      FTextStream := Value;
      if Assigned(FTextStream) then
        FTextSize := FTextStream.Size;
    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 à l'essai
    Profil pro
    Inscrit en
    Avril 2012
    Messages
    23
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2012
    Messages : 23
    Points : 22
    Points
    22
    Par défaut
    Finalement, j'ai pu initialiser la Progressbar avec ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
          AssignFile(FichTest, FileName);
          Append(FichTest);
          ProgressBar1.Max := FilePos(FichTest);
          ProgressBar1.Position := 0;
          Reset(FichTest);
          while not Eof(FichTest) do
          Begin
            ProgressBar1.Position := FilePos(FichTest);
            {Do somethink}
          End;

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

Discussions similaires

  1. Lire fichier text avec dlmread
    Par callofduty dans le forum MATLAB
    Réponses: 12
    Dernier message: 07/08/2013, 22h49
  2. Lire fichier texte
    Par kinouseb dans le forum VC++ .NET
    Réponses: 2
    Dernier message: 08/11/2006, 18h01
  3. Lire fichier texte en respectant la police, la forme
    Par loupin dans le forum Langage
    Réponses: 2
    Dernier message: 10/07/2006, 23h49
  4. Lire fichier Texte
    Par rprom1 dans le forum Entrée/Sortie
    Réponses: 12
    Dernier message: 15/03/2006, 17h36
  5. Réponses: 3
    Dernier message: 05/04/2005, 12h52

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