Recherche dans un fichier texte.

Résolu
vico8000
Messages postés
287
Date d'inscription
lundi 18 janvier 2016
Statut
Membre
Dernière intervention
14 février 2018
- 14 juin 2016 à 08:15
vico8000
Messages postés
287
Date d'inscription
lundi 18 janvier 2016
Statut
Membre
Dernière intervention
14 février 2018
- 29 juin 2016 à 10:25
Bonjour,

j'explique mon problème.

J'ai un petit programme à faire pour récupérer une partie d'un fichier .txt à l'aide d'un intervalle d'octet (Ex: [56000;58000], va me donner le texte compris entre le 56000 et 58000 octet)
Un octet est "grossièrement" 1 caractère. (Hormis pour les retours à la ligne qui comptent pour 2 octets).
Mon intervalle d'octet est stocké en base de données. La récupération de ces données n'est pas un problème.
Je ne vois, à l'inverse, pas par quelle méthode, ou comment je pourrais faire pour rechercher dans mon fichier .txt avec les octets directement.
Je pourrais, je ne sais par quel procédé, compter les caractères dans mon fichier .txt ? et compter 2 fois si j'ai un retour à la ligne ?
sachant que les fichiers .txt sont très volumineux. (2MO < x < 4MO)

Je reste à votre disposition si je n'ai pas été clair.
Cordialement, et par avance, merci.

6 réponses

vico8000
Messages postés
287
Date d'inscription
lundi 18 janvier 2016
Statut
Membre
Dernière intervention
14 février 2018
2
29 juin 2016 à 10:25
A final, j'ai trouvé une alternative pour mes recherches.

Sachant que je ne peux pas me fier aux Octets dû à des incohérences dans la base de données. (Société extérieure donc indépendante de toute modification)

Je pose donc mon code dans le cas ou certaines personnes auraient le même type de recherche à effectuer.

Je prend une partie d'un fichier et je la copie dans un fichier créé.
On effectue ensuite notre lecture et on copie dans le fichier fraîchement créé.
A chaque "bilan apprentissage" on s’arrête, on recréé un nouveau fichier et ainsi de suite jusqu'à arriver en fin de fichier.

PROCEDURE traitement.CreationFichier(Date : String);
var
Recuperation : integer;
Filedelete : String;

BEGIN
FichierName := 0; // Creation du CR unique ( Provisiorement )

//Ouverture du fichier CR jour
AssignFile(myFile, 'C:\Users\Administrateur\Desktop\DatasBAF2A\CR' + date + '.txt');
Reset(myFile);
//Création du fichier CR unique
AssignFile(newFile, 'C:\Users\Administrateur\Desktop\test\Fichier_'+ date + '_' + inttostr(FichierName) + '.txt');
Rewrite(newFile);

//tant que nous ne sommes pas en fin de fichier
WHILE NOT Eof(myFile) DO
BEGIN
ReadLn(myFile, Stg);
//Découpage repéré par la ligne de bilan apprentissage
IF (Stg = '/11************************* BILAN APPRENTISSAGE 1***************** ' ) THEN
BEGIN
FichierName := FichierName + 1;
CloseFile(newFile);
AssignFile(newFile, 'C:\Users\Administrateur\Desktop\test\Fichier_'+ date + '_' + inttostr(FichierName) + '.txt');
Rewrite(newFile);
END;
WriteLN(newFile, Stg);
END;

CloseFile(myFile);
CloseFile(newFile);

END;
1
nagaD.scar
Messages postés
4269
Date d'inscription
samedi 8 septembre 2007
Statut
Membre
Dernière intervention
4 mars 2021
16
Modifié par nagaD.scar le 14/06/2016 à 17:01
Salut,

Je souhaiterai juste dans un premier temps parler des tailles:

- 1 octet représente un caractère, pas "grossièrement" mais tout cours.
- une fin de ligne peu être sur un ou deux octets en fonction de l encodage => soit c'est "\r\n" donc 2 caractères , soit "\r" soit "\n" donc 1 caractère (rappel: 1 caractère est sur 1 octet).

Une chose a savoir aussi, un fichier peu contenir un en-tête (par exemple un encodage utf8 bom ajoutera 2 caractères) => en gros il faut que tu connaisse l encodage pour déterminer la valeur a soustraire au final.

Ensuite, sachant qu'un caractère=un octet, il te suffit de récupérer la taille du fichier (a prioris c'est la fonction FileSize de system - elle renvoi la taille en octets ... parfais !).
si le fichier a une entete, soustrait la taille.

Aussi, tu peux retirer 1 caractère pour le "end of file".

Maintenant tu connais le nombre de caractères, incluant les saut de ligne.

Pour savoir quel est (quels sont) le(s) caractère(s) de fin de ligne, lis caractère par caractère et fais un check (dès que tu termine la première ligne, stop)


Par contre pour connaitre le nombre de lignes, il va falloir que je sache si la taille d une ligne est fixe (là c'est simple) ou non ... et si non, pas le choix il va falloir que tu lises une fois tout le fichier pour savoir.

Je suis pas sûre d'être complètement dans le sujet, je pense qu'il manque des choses que je n'ai pas bien compris mais en lisant ca tu pourra au moins avoir des point pour rendre ta demande plus claire ^^

naga
0
vico8000
Messages postés
287
Date d'inscription
lundi 18 janvier 2016
Statut
Membre
Dernière intervention
14 février 2018
2
Modifié par vico8000 le 15/06/2016 à 09:02
Bonjour,

Le saut de ligne est codé sur 2 Octets. (Linux/Unix pour les sauts de ligne sur 1 octet ?)

Je suis en encodage Utf-8. Malgré tout, les deux octets d'en-tête et l'octet de fin de fichier sont-ils à prendre en compte ? (Je ne pense pas, j'aurais des incohérences dans mes données après)

Merci pour la fonction FileSize, je me pencherais dessus un peu plus tard. (Je stocke de l'information sur comment procéder avant de commencer le développement)


"Par contre pour connaitre le nombre de lignes, il va falloir que je sache si la taille d une ligne est fixe (là c'est simple) ou non ... et si non, pas le choix il va falloir que tu lises une fois tout le fichier pour savoir."

Je vais donc être obligé de lire ligne par ligne, ma taille de ligne n'est absolument pas fixe. Le fait d'avoir des fichier avec 3M de caractères ne va pas provoquer des problèmes de latence ?


Dans l'idée (si je n'ai pas été clair), je souhaiterai développer une application pour mon entreprise, afin de faire une recherche d'erreurs dans un fichier texte.
Une machine nous sort un rapport journalier dans un fichier texte et remonte certaines données dans une BDD.
Actuellement, nous ne faisons pas le lien entre les deux.
Dans la base de données, nous avons en "gros" une date, et un nombre d'octets. (beaucoup plus compliqué que ça dans la réalité mais le reste des champs ne rentrent pas en compte pour ce projet)
Le nombre d'octets stockés dans la base de données se présentent sous cette forme:
- Le premier enregistrement prend 700 Octets, champ Octet=700
- Le deuxième enregistrement prend 500 Octets, champ Octet=1200
- ...

Dans ce rapport journalier, est édité toutes les erreurs qui sont survenues.
Le but serait donc, depuis l'application, de choisir une date dans un listbox. Cette dernière va chercher le champ octet correspondant. Nous avons notre fin d'enregistrement désiré.
Nous regardons l'enregistrement précédent de celui que nous venons d'avoir pour récupérer à nouveau le champ octet. Celui-ci nous donnera notre début de lecture.
Enfin, afficher ce que nous avons été rechercher.

J’espère avoir été le plus clair possible.
Sinon, je reste toujours à disposition.

Cordialement.
0
Whismeril
Messages postés
17493
Date d'inscription
mardi 11 mars 2003
Statut
Modérateur
Dernière intervention
6 juillet 2022
601
15 juin 2016 à 09:11
Bonjour, si ton but est de récupérer toutes les occurrences d'un pattern : 2 entiers entre crochets séparés pas ; alors tu peux regarder du côté des regex.
0
vico8000
Messages postés
287
Date d'inscription
lundi 18 janvier 2016
Statut
Membre
Dernière intervention
14 février 2018
2
15 juin 2016 à 09:24
Régular Expression, ce n'est pas pour rechercher dans le texte par un mot clé ?
Je n'ai jamais eu l'occasion d'utilisé ce type de fonction.

Cordialement.
0
Whismeril
Messages postés
17493
Date d'inscription
mardi 11 mars 2003
Statut
Modérateur
Dernière intervention
6 juillet 2022
601
15 juin 2016 à 14:21
Non justement c'est pour mettre un pattern
0

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

Posez votre question
nagaD.scar
Messages postés
4269
Date d'inscription
samedi 8 septembre 2007
Statut
Membre
Dernière intervention
4 mars 2021
16
15 juin 2016 à 10:20
Je commente les deux réponses:
- "Le saut de ligne est codé sur 2 Octets. (Linux/Unix pour les sauts de ligne sur 1 octet ?) ". Il me semble que c'est le cas par défaut, mais ca ne sous entends pas que tu ne trouvera l'inverse (au final c'est l encodage qui importe).

- Concernant la lecture du fichier, si l idée est de faire un passage préalable (en background, juste pour connaitre les positions), ca ne provoquera pas de latence vu que pas d'utilisateur. Ensuite si a chaque demande tu fais la lecure oui ca risque de provoquer une latence, mais pour un fichier de petite taille, c'est négligeable (a la louche, le parcours complet prendra entre 0.5 et 4 secondes) ... bien sûr ca dépendra des tests (si tu fais 50 test pour chaques caractères, ca sera plus long).

- Concernant les regex, grossomodo oui c'est une recherche par mot clef dans du texte mais "conditionable" (je veux pas expliquer, trop long, mais fais un tour sur le net et tu comprendra vite).

Pour ce qui est de ton projet,


Une machine nous sort un rapport journalier dans un fichier texte et remonte certaines données dans une BDD.
Actuellement, nous ne faisons pas le lien entre les deux.
Dans la base de données, nous avons en "gros" une date, et un nombre d'octets. (beaucoup plus compliqué que ça dans la réalité mais le reste des champs ne rentrent pas en compte pour ce projet)


Si je comprends bien, tu possèdes déjà toutes les infos non?

Là je t avoues que je suis perdu .. tu possède le fichier et tu peux accéder au descriptif. Quand tu dis qu'il n y pas de lien, que sous entends tu?
0
nagaD.scar
Messages postés
4269
Date d'inscription
samedi 8 septembre 2007
Statut
Membre
Dernière intervention
4 mars 2021
16
15 juin 2016 à 10:30
Ok j y suis : tu identifie ce que t’intéresse grâce à la date -> il n y a qu'un fichier/jours d'extrait).

Du coup ce que je ne comprends pas c'est pour quelle raison as-tu besoin de connaitre la taille de ton fichier?

En fait, tu connais les positions de départ et tailles (en octets) et tu ne sais pas comment récupérer les données dans le fichier directement?
De plus, du coup je ne comprends pas la raison de calculer le nombre d'octets de saut de lignes ou quoi que ce soit=> ta bdd indique la taille, en théorie lors de l insertion en base il va pas s amuser à soustraire les sauts de ligne, ca serai incohérent, ils sont tout autant pris en compte => lors de l insertion il doit simplement récupérer la taille actuelle du fichier, soustraire la derniere taille lue et faire son insertion, c'est tout.

Et donc du coup pour lire un intervalle définit, tu as fseek pour te positionner dans ton fichier, puis tu n'as plus qu'à lire le nombre de caractères voulu.


Bon mes deux réponses sont un peu brouillon mais voila ^^
0
vico8000
Messages postés
287
Date d'inscription
lundi 18 janvier 2016
Statut
Membre
Dernière intervention
14 février 2018
2
15 juin 2016 à 10:34
J'ai besoin de récupérer les Octets parce que la base de données me donne une date et une heure + un nombre d'octet la ou le fichier texte me donne uniquement une date ( en nom de fichier )
Cordialement
0
nagaD.scar
Messages postés
4269
Date d'inscription
samedi 8 septembre 2007
Statut
Membre
Dernière intervention
4 mars 2021
16
15 juin 2016 à 11:29
ok donc ca veut dire que tu as besoin de récupérer l'heure? Car en fait, grâce à la dateheure dans ta bdd, tu peux identifier le fichier et le nombre d octets à lire, l enregistrement précédent t'indiquant le point de départ - 1.

Je penses que tu cherche dans la mauvaise direction, si j'ai bien saisi le lien => dans ta futur appli, tu va sélectionner une date, cette date permettant de filtrer la base de données et d'identifier le fichier.
Si j'ai compris, tu ne veux récupérer que les erreurs dans le fichier. Donc: comment sais-tu qu un enregistrement est en erreur? ta bdd a t'elle l'info? OU tu ne le sait que lors de la lecture du fichier?
Si tu as l info en base, tu devra donc sélectionner les lignes d'erreur, récupérer la description ( départ+taille ) et afficher les résultats.
Si tu n as pas l info en base, et donc que l info d'erreur est dans la ligne du fichier, le requête n a pas d’intérêt: tu devra lire ligne a ligne et n'afficher que les lignes d'erreurs.

Mais en fait à aucuns moment il n'est nécessaires de connaitre la taille de ton fichier ou autre: soit tu lis ligne a ligne en te basant sur le(s) caractère(s) de fin de ligne, soit tu récupères les octets à lire depuis ta bdd, le reste n'est pas utile (sauf dans le cas ou les données dans ta bdd sont erronées et possède des enregistrement en dehors du fichier mais la le problème ne concerne pas le scope actuel)
0
vico8000
Messages postés
287
Date d'inscription
lundi 18 janvier 2016
Statut
Membre
Dernière intervention
14 février 2018
2
15 juin 2016 à 12:17
En effet, je pense que je partais dans la mauvaise direction.
Après réflexion, le fichier et la base de données ne se croisent pas. ( Alors que cela devrait, problème avec les appli externes ou tu n'as pas la main dessus ) Le nombre d'octet stocké en base de données est incohérent. je ne peux donc pas faire le lien avec mon fichier. De plus, un fichier à part est crée avec les erreurs (matérialisées par un code /xxxxxxx). il faut que je fasse donc le lien avec ce fichier au lieu du précédent. Dans ma base de données, il est indiqué quand j'ai une erreur. Il me suffit juste de compter le nombre d'erreurs avant la date sélectionnée pour retrouver le bon code. Le principe à l'air beaucoup plus simple dans ce sens la. Il n'y a aucune conversion à effectuer, ...
De plus, si j'ai besoin à un moment quelconque de compter les octets, je pourrais le faire plus aisément puisque toutes les lignes sont de la même dimension et les différents temps sont séparés par un saut de ligne.
Du coup je fais une boucle qui test toute la base de données pour erreur!=0 et quand erreur différent de 0 je passe dans un listbox l'heure et la date.
0
nagaD.scar
Messages postés
4269
Date d'inscription
samedi 8 septembre 2007
Statut
Membre
Dernière intervention
4 mars 2021
16
15 juin 2016 à 12:25
Ok!

Du coup tu as trouvé ta solution à prioris ^^ n'hésites pas a redemander si tu coinces !
naga
0
Salut,
Pour "rechercher / utiliser" un fichier texte il existe plusieurs solutions, TFileStream, TMemoryStream, TStringStream, File, TextFile, TStringList,... tout dépend de la structure du fichier. Si tu connais la position dans le fichier texte alors TFileStream, TMemoryStream... permet de se positionner où l'on souhaite, avec par exemple Position, Seek et ensuite lire la longueur que l'on veut en incluant les "caractères" de fin de ligne, tabulation etc... et même gérer les encodages avec TEncoding.
Si dans le fichier texte la structure est bien défini avec des trames style fichier csv, "", ; : / ou fixe comme un record TStringList et TextFile peuvent très bien faire le taf...
La réponse et la solution à ta question est très variable de la structure du fichier texte et de la façon de se déplacer et de l'utiliser...Peut-être vas tu trouver la solution dans les termes que je t'ai donné.
@+
0