|
Importation d'un fichier texte de longueur fixe |
|
Developpeur WDF
Inscrit: 10/02/2005 14:25
De Lille
Post(s): 123
|
Bonjour a tous,
J'ai une petite question :
Comment importer un fichier de longueur fixe???
J'ai fais le découpage et je récupère la taille de chaque champ afin de créer mon fichier HF par programmation.
Je voulais savoir si il y avait une autre manière d'importer le fichier???
Ma procédure est la suivante :
Ayant le nombre de caractères pour chaque champ,j'utilise fLit pour lire le fichier texte et HEcrit pour écrire les données dans le fichier HF
fLit(IDFichier,NbCaractères,&AdresseMémoire) NomFichierHF.NomChamp=AdresseMémoire HEcrit(NomFichierHF,HNbEnr,hEcritureDefaut)
Le probleme c'est que cela est extremement long...(environ 14 secondes pour 1926 lignes de 192 caractères - ODOA inclus)
Merci d'avance pour votre aide
Cordialement
Nico
Contribution le : 24/03/2005 17:32
|
|
|
Re: Importation d'un fichier texte de longueur fixe |
|
Animateur WDF
Inscrit: 26/06/2002 16:24
De wdforge.org
Post(s): 2822
|
hImporteTexte est EXTREMEMENT rapide (même incompréhensible de vitesse...).
Sinon, pour avoir réalisé une intégration de fichiers (à largeur fixe ou variable mais surtout extrèmement paramétrable (description source et description cibles dans fichiers liés) : nous somme passé par une lecture du fichier texte par bloc et non par ligne. L'accès mémoire étant plus rapide que l'accès disque on économise les fLitLigne. Dans notre cas, on produit ensuite autant de txt 'prêt à hImporter' que nécessaire et lançons les himportetexte après avoir sérieusement analysé le txt.
Nous somme arrivé à des performance honorables (bien qu loin de ce que l'on pourrait faire en C mais il faut maintenir la solution...) et avons ensuite traqué les fuites de mémoire.
ps : on partait au départ de 1.5 heure pour lire et analyser le txt et on est à une toute petite dizaine de minute (tous contrôles compris).
Le code de la lecture en bloc pourrait donner lieu à une ressource... mais faudra être trés gentil !
Contribution le : 24/03/2005 17:43
|
|
|
Re: Importation d'un fichier texte de longueur fixe |
|
Developpeur WDF
Inscrit: 10/02/2005 14:25
De Lille
Post(s): 123
|
Je comprends pas trop... La lecture en bloc se fait bien avec fLit(IDFichierHF,NbOctets,1&AdresseMémoire)? Citation : Dans notre cas, on produit ensuite autant de txt 'prêt à hImporter' que nécessaire et lançons les himportetexte après avoir sérieusement analysé le txt. A partir de ton fichier texte tu le dévoupe en plusieurs fichiers???? Pourrait tu me donner plus d'infos Cordialement Nico
Contribution le : 24/03/2005 17:58
|
|
|
Re: Importation d'un fichier texte de longueur fixe |
|
Animateur WDF
Inscrit: 26/06/2002 16:24
De wdforge.org
Post(s): 2822
|
Oui, effectivement fLit fait cela trés bien pardon et passe direct par adresse en plus.
Pour le reste, je prépare un autre fichier texte formaté à ce qu'attend ma base de donnée (mon fichier en fait si la description du fichier d'origine ne onvient pas à un hImporteTexte) pour l'utiliser ensuite dans un hImporteTexte.
En effet, cette fonction est sensiblement (euphémisme) plus rapide qu'autant de hajoute + maj des index que de lignes lues... C'est ce qui fait la différence.
Enfin, dans mon cas, le fichier texte partant dans plusieurs fichier HyperFile, je dois donc préparer donc plusieurs txt temporaires.
L'astuce fut de penser à passer par un fichier intermédiaire pour gagner du temps (l'espris de contradiction sans doute). Résultat : plus le volume est grand, plus le gain l'est aussi.
Contribution le : 24/03/2005 18:11
|
|
|
Re: Importation d'un fichier texte de longueur fixe |
|
Anonyme
|
Donc si je résume Il faut que je lise le fichier texte source Ensuite je le formate (par exemple en séparant les champs par des ) Et pour finir j'utilise hImporteTexte
Je me pose la question suivante :
si je recrait un fichier texte formaté ca sera aussi long???
A moins que je récupère le tout dans une chaine (2Go Max) Que j'insere un caractere de séparation au bon endroit J'écrit le fichier texte formaté avec ma chaine formaté et je l'importe avec hImporteTexte
Qu'en penses tu???
Sinon, je pensais a créer un Thread qui me récupère le contenu du fichier pendant que l'utilisateur le découpe.
Contribution le : 24/03/2005 20:26
|
|
|
Re: Importation d'un fichier texte de longueur fixe |
|
Animateur WDF
Inscrit: 26/06/2002 16:24
De wdforge.org
Post(s): 2822
|
Exactement ! Saisie1 = fChargeTexte ("C:\Temp\MonFichier.txt")
// parcours de saisie1 ligne à ligne et écriture dans Saisie2 formatée
IdFichierTemporaire = fouvre(nomtemporaire,foCreation+foEcriture)
SIidFichierTemporaire = -1 ALORS
erreur()
RETOUR
FIN
ResEcriture = fEcrit (IdFichiertemporaire, saisie2)
FFerme(idFichierTemporaire)
hImporteTexte(FichierHF,nomtemporaire, "RUB1,RUB2...",TAB+Caract(127)+""""+Caract(127)+RC, hImpSansDélimiteur+hImpIgnoreLigneInvalide+hImp_Autres_Paramètres , "Jauge1")
Noter que les séparateurs on été défini pour un fichier avec TAB comme délimiteur de colonnes et RC pour les lignes. Pour le reste (utilisateur qui "découpe" le fichier) il faut étudier sur cas car il n'est pas évident detenir compte du délai d'action de l'utilisateur...
Contribution le : 25/03/2005 08:43
|
|
|
Re: Importation d'un fichier texte de longueur fixe |
|
Developpeur WDF
Inscrit: 10/02/2005 14:25
De Lille
Post(s): 123
|
Merci beaucoup Je vais essayer tout de suite et je tiens au courant
Contribution le : 25/03/2005 09:00
|
|
|
Re: Importation d'un fichier texte de longueur fixe |
|
Developpeur WDF
Inscrit: 10/02/2005 14:25
De Lille
Post(s): 123
|
OK j'ai fini je passe de 14 secondes a 3 secondes pour 1926 lignes de 192 caractères Ce qui me parait convenable même si Access me parait plus rapide (pour l'importation)
Je vais faire des tests sur des ficheirs plus volumineux
Contribution le : 25/03/2005 11:15
|
|
|
Re: Importation d'un fichier texte de longueur fixe |
|
Animateur WDF
Inscrit: 26/06/2002 16:24
De wdforge.org
Post(s): 2822
|
C'est l'histoire d'un mec qui parvient à diviser son temps d'éxécution par presque 5 et qui rechigne... Si j'indique que le gain à utiliser cette méthode est croissant avec le volume, que va-t on entendre ? PS : Mieux avec ACCESS ? Mais il y a aussi le C ! En revanche il faudra un peu plus qu'une dizaine de ligne et pas mal de compétence technique (pointeurs, pipes et threads entre autres) PPS : non je ne suis pas énervé
Contribution le : 25/03/2005 11:52
|
|
|
Re: Importation d'un fichier texte de longueur fixe |
|
Developpeur WDF
Inscrit: 10/02/2005 14:25
De Lille
Post(s): 123
|
J'ai travaillé sur Access avant de me lancer en Windev Pourquoi délaisser Access? Parce que c'est buggé a mort... Exemples de bugs que j'ai rencontré : 1 - Tri + création d'une table via une requete SQL (liant une table de tri a la table d'adresses a trier) Résultat: aléatoirement des enregistrements se placent au début alors que le reste du tri est bon La seule solution que j'ai trouvé et qui marche c'eatit d'exporter directement le résultat de la requete sans passer par une création de table 2 - Fonction d'importation de fichier texte Il était soit disant possible d'importer un fichier avec un parametre d'import se trouvant dans un fichier .INI Apres de longue recherche j'ai rouvé sur le site de Microsoft que la fonction ne focntionnait pas et qu'il fallait passer par une requete d'importation avec des paramètres assez complexe Enfin voila pourquoi je suis passé a Windev et j'avoue que je ne suis pas deçu Bref J'ai un probleme car avec des fichiers contenant peu d'enregistrement (<5000 lignes) ca fonctionne Par contre, qd je veux importer un fichier plus grand (15000 lignes) et que je veux passer en mode pas à pas a chaque ligne, dans le gestionnaire des taches le processeur affiche 100% d'utilisation et la mémoire se charge... Je ne comprends pas trop ce qui se passe Résultat: en mode pas a pas ca met 30secondes avant de passer a la ligne suivante Une idée???
Contribution le : 25/03/2005 12:06
|
|
|
Re: Importation d'un fichier texte de longueur fixe |
|
Animateur WDF
Inscrit: 26/06/2002 16:24
De wdforge.org
Post(s): 2822
|
OK, Il faut tenter de localiser où le code ralenti, il s'agit sans doute d'une fuite de mémoire. La solution que nous avons trouvé est alors de faire en sorte de ne pas avoir d'allocation mémoire dans la boucle. Effectivement Windows est ainsi fait, qu'à force d'allocation mémoire (déclarations de variables dans la boucle), il pagine trés vite la mémoire et vous vous retrouvez à utiliser l'espace swap disque... qui n'a plus rien à voir en terme de performance. Si vos déclaration se font en longueur fixe (c'est un chance car tel est votre cas), déclarez vos variables de lectures des zones dans des chaine à longueur fixe aussi et ce en dehors de la boucle. Voici aussi un peu de lecture pour le long week end à venir. Cela pourrait être utile pour traiter la structure de vos lignes.... Encore un gain : l'utilisation de la fonction transfert() en des points opportuns et que sais-je... ?
Contribution le : 25/03/2005 12:35
|
|
|
Re: Importation d'un fichier texte de longueur fixe |
|
Developpeur WDF
Inscrit: 10/02/2005 14:25
De Lille
Post(s): 123
|
Voici la partie de mon code concernant le formatage du texte d'origine, l'écriture du fichier texte (teporaire) formaté et l'importation Mes varaiables sont déclarées au début e la procédure hors des boucles et pourtant sur une chaine de 6Mo ca rame a fond Je ne vois pas où peuvent être les fuites mémoires... Tu peux m'aider STP Merci beaucoup pour ton aide qu m'a permis=e d'avancer Je pense que je ne suis pas loin //Chargement du fichier texte complet
TexteOrigine=fChargeTexte(cNomFichier)+EOT
//on ajoute 2 pour le RC
LongMax=LongMax+2
//On récupère la premiere ligne
LigneOrigine=Gauche(TexteOrigine,LongMax)
//initialisation du compteur
nCompteur=1
TANTQUE Droite(LigneOrigine,1)<>EOT
i=1
LigneFormate=Gauche(LigneOrigine,tNbCarFixe[i])+TAB
PosLecture=tNbCarFixe[i]+1
i++
TANTQUE i<=NbElt
SI i<NbElt ALORS
LigneFormate=LigneFormate+Milieu(LigneOrigine,PosLecture,tNbCarFixe[i])+TAB
PosLecture=PosLecture+tNbCarFixe[i]
SINON
LigneFormate=LigneFormate+Milieu(LigneOrigine,PosLecture,tNbCarFixe[i])
FIN
i++
FIN
TexteFormate+=LigneFormate+Caract(13)+Caract(10)
LigneOrigine=Milieu(TexteOrigine,(LongMax*nCompteur)+1,LongMax)
nCompteur++
FIN
FichierTemp="c:\TexteTemp.txt"
fSauveTexte(FichierTemp,TexteFormate)
cSep=TAB+Caract(127)+""""+Caract(127)+RC
OuvreFille(FenJauge)
SI HImporteTexte(cNomFichierHF,FichierTemp,cRub,cSep,hImpSansDélimiteur+hImpIgnoreLigneInvalide,FenJauge)=True ALORS
Ferme(FenJauge)
HFin=HeureSys
Info("Importation réalisée avec succès.")
SINON
Erreur("Erreur d'importation.")
FIN
Contribution le : 25/03/2005 15:32
|
|
|
Re: Importation d'un fichier texte de longueur fixe |
|
Animateur WDF
Inscrit: 26/06/2002 16:24
De wdforge.org
Post(s): 2822
|
TANTQUE Droite(LigneOrigine,1)<>EOT
Mon dieu, vous traitez octet par octet ? Réfléchissons, vous connaissez la structure devotre fichier lu ? les rubriques sont exprimée en longueur (faute de séparateur) ? Pourquoi ne pas prévoir alors la lecture dans un tableau de structure la ligne entière d'un seul coup en jouant avec les positions ? VarRub = SansEspace(Milieu(Texte_ligne,RubDebut,RubLongueur))
Enfin, pour économiser de la mémoire, pourquoi ne pas lire le fichier par blocs (de tailles honorable : 1 Mo à la fois par exemple)... il suffit simplement de conserver les lignes inachevée (dont taille <à somme des tailles de zone si ne fini pas pas un RC) pour concaténer au bloc suivant... jusqu'à fin de fichier. Un enchainement de boucles pourra alors lire les lignes (entres les positions des RC) du bloc lu dans le fichier. Pour info, il suffit de boucler sur : PROCEDURE LigneLire()
Pos_Fin=Position(texte_bloc,Caract(10),Pos_Debut)
Texte_ligne = texte_bloc[[Pos_Debut A Pos_Fin-2]]
RENVOYER Texte_ligne
PROCEDURE LigneSuivante()
Pos_Debut=Pos_Fin+1
Vous deviez en sortir maintenant, sinon je me déplace volontier...
Contribution le : 25/03/2005 16:25
|
|
|
Re: Importation d'un fichier texte de longueur fixe |
|
Developpeur WDF
Inscrit: 10/02/2005 14:25
De Lille
Post(s): 123
|
Ok je vais rentrer chez moi (là je suis au boulot)et je vais tester ca... PS : je viens de me rendre compte d'une chose Mon chef m'avait demandé de partager le projet (ce que j'ai fais...) mais j'avais oublié que le chemin de mon projet était en réseau (quel abruti...) (Ex: \\MonOrdinateur\Mes projets\Gestionnaire d'importation\Gest_Import.WDP) Tu m'étonnes que c'était extremement long.... Bon remettons les choses au clair avec un chemin local: Importation d'un fichier de 44000 Lignes(10 champs) : 19 secondes (c'est deja mieux) et 0.36 secondes pour 2000 lignes (6 champs) Maintenant il faut que je l'optimise avec vos dernieres remarques et je pense que cela devrait etre bon Encore merci Je vous tiens au courant Cordialement PS2 : TANTQUE Droite(LigneOrigine,1)<>EOT
c'était un controle pour tester la fin du fichier (peut etre inutile...dsl)
Contribution le : 25/03/2005 17:00
|
|
|
Re: Importation d'un fichier texte de longueur fixe |
|
Developpeur WDF
Inscrit: 10/02/2005 14:25
De Lille
Post(s): 123
|
Desole pourle temps que j'ai mis mais j'etais en week end prolongé et je n'étais pas chez moi donc voila ce qui explique la cause du retard. Sinon j'ai travaillé en suivant vos conseils et j'ai encore gagné 7-8 secondes (Import 44000 lignes (10 champs) -> 11 a 12 secondes) Vous me dites d'utiliser un tableau de structure pour la lecture du fichier en se déplacant. La, je me pose une question : Est il possible de boucler pour créer des variables (je pense que non) alors comment decrire la structure??? Voici ma procédure //declaration de la structure
sStructFichier est une structure
cRubrique est une chaîne
FIN
//declaration du tableau
tTabLignes est un tableau de 0 sStructFichier
ResLecture est un entier
//Nombre d elements dans le tableau contenant le nombre de caracteres par champs
NbElt=Dimension(tNbCarFixe)
PosTemp est un entier=1
j=1
P_Debut=1
SI IDFich<>-1 ALORS
//Lecture du premier Mo
ResLecture=fLit(IDFich,1000000,&AdresseChaine)
//Si pas d'erreur
SI ResLecture<>0 ALORS
Texte_Bloc=AdresseChaine
FIN
TANTQUE Taille(Texte_Bloc)<>0
i=1
//On lit une ligne(jusqu'au RC)
Texte_Ligne=LigneLire()
//Si la taille de la ligne est inférieure a la taille d'une ligne fixe du fichier
SI Taille(Texte_Ligne)<LongMax ALORS
//On lit 1Mo que l'on concatene au reste de la chaine précédente
ResLecture=fLit(IDFich,1000000,&AdresseChaine)
//Si pas d'erreur
SI ResLecture<>0 ALORS
Texte_Bloc=Texte_Ligne+AdresseChaine
P_Debut=1
Texte_Ligne=LigneLire()
SINON
//On est a la fin du fichier donc on sort de la boucle
SORTIR
FIN
FIN
//on ajoute une ligne au tableau
TableauAjoute(tTabLignes)
PosTemp=1
//Formatage de la ligne lue et affectation au tableau de structure
TANTQUE i<=NbElt
SI i=1 ALORS
tTabLignes[j]:cRubrique+=SansEspace(Milieu(Texte_Ligne,1,tNbCarFixe[i]))
SINON
tTabLignes[j]:cRubrique+=(TAB+SansEspace(Milieu(Texte_Ligne,PosTemp,tNbCarFixe[i])))
FIN
PosTemp+=tNbCarFixe[i]
i++
FIN
tTabLignes[j]:cRubrique+=RC
j++
LigneSuivante()
FIN
FIN
TexteAEcrire est une chaîne
IDFich2 est un entier
Fichiertemp est une chaîne="c:\texteTemp.txt"
cSep est une chaîne
IDFich2=fOuvre(Fichiertemp,foCréation+foAjout)
//Ecriture dans le fichier temporaire par bloc de 1Mo minimum
POUR i=1 A Dimension(tTabLignes)
SI Taille(TexteAEcrire)>=1000000 ALORS
TexteAEcrire+=tTabLignes[i]:cRubrique
fEcrit(IDFich2,TexteAEcrire,Taille(TexteAEcrire))
TexteAEcrire=""
SINON
TexteAEcrire+=tTabLignes[i]:cRubrique
FIN
FIN
fEcrit(IDFich2,TexteAEcrire,Taille(TexteAEcrire))
TexteAEcrire=""
Lecture des lignes : PROCEDURE LigneLire()
P_Fin=Position(Texte_Bloc,Caract(10),P_Debut)
SI P_Fin<>0 ALORS
Texte_Ligne=Texte_Bloc[[P_Debut A P_Fin-2]]
SINON
Texte_Ligne=Texte_Bloc[[P_Debut A Taille(Texte_Bloc)]]
FIN
RENVOYER Texte_Ligne
Passage a la Ligne Suivante : PROCEDURE LigneSuivante()
P_Debut=P_Fin+1
Contribution le : 30/03/2005 17:24
|
|
|
Re: Importation d'un fichier texte de longueur fixe |
|
Developpeur WDF
Inscrit: 10/02/2005 14:25
De Lille
Post(s): 123
|
Bon, ce que j'ai fais avec le tableau de structure ne sert a rien...Autant déclaré un tableau de chaine ce qui reviens au même et la je passe sous la barre des 10 secondes...
Contribution le : 30/03/2005 17:33
|
|
|
Re: Importation d'un fichier texte de longueur fixe |
|
Animateur WDF
Inscrit: 26/06/2002 16:24
De wdforge.org
Post(s): 2822
|
Citation : Est il possible de boucler pour créer des variables (je pense que non) alors comment decrire la structure??? Je pense qu'il vous faut vite lire ce dossier qui traite du sujet. ps : merci pour vos message, et désolé pour le contre temps piscicole.
Contribution le : 04/04/2005 10:47
|
|
|
Re: Importation d'un fichier texte de longueur fixe |
|
Anonyme
|
Oufff on est sauvé Hip hip hip Ouraahhh...Je veux une innovation pour WDFORGE C trop cool, franchement g eu les jetons qd j'ai vu le message de cloture...enfin ce n'est qu'un mauvais souvenir a present... Bon, Ne connaissant la structure de mon fichier (rubriques exprimées en longueur) qu'au moment de l'importation comment déclarer la structure??? Je dois utiliser l'instruction de compilation dynamique (Compile()) dans laquelle j'entre le code qui contient la description de mes variables Ex:
sChaine est une chaine
sChaine= "sStruct est une structure
Rub1 est une chaine
Rub2 est une chaine
Rub3....."
Compile(sChaine)
et apres j'utilise la structure ainsi créée???
Contribution le : 05/04/2005 11:03
|
|
|
Re: Importation d'un fichier texte de longueur fixe |
|
Animateur WDF
Inscrit: 26/06/2002 16:24
De wdforge.org
Post(s): 2822
|
Oui... C'est une voie. Dernier élément avant consultance sur site (héhé, c'est possible aussi).
Dans notre cas le tableau de structure sert pour décrire respectivement chaque zone (rubrique cible, largeur, séparateur et nombre de décimales...). Les valeurs sont alors décrite dans une fenêtre et enregistrés dans un INI.
C'est le parcours du tableau de structure qui permet de comprendre la description d'une ligne. La structure décrivant une 'rubrique', le tableau décrit une ligne.
Pour la compilation dynamique on l'utilise aussi mais à d'autres fins.
Contribution le : 05/04/2005 11:20
|
|
|
Re: Importation d'un fichier texte de longueur fixe |
|
Anonyme
|
Donc si j'ai bien compris la structure se comporte dans ce style :
sStructFichier est une structure
sRub est une chaine //Contenu de la rubrique
nTaille est un entier //taille de la rubrique
sSep est une chaine //caractère de séparation (TAB dans mon cas)
nNbDec est un entier //Nombre de décimales
FIN
Je vais essayer pour voir si je peux encore gagner du temps Mais je pen,se que c deja pô mal ce que j'ai fais Encore merci et j'espere me développer encore un peu afin de vous donner un coup de main
Contribution le : 05/04/2005 11:35
|
|
Vous ne pouvez pas débuter de nouveaux sujets.
Vous pouvez voir les sujets.
Vous ne pouvez pas répondre aux contributions.
Vous ne pouvez pas éditer vos contributions.
Vous ne pouvez pas effacez vos contributions.
Vous ne pouvez pas ajouter de nouveaux sondages.
Vous ne pouvez pas voter en sondage.
Vous ne pouvez pas attacher des fichiers à vos contributions.
Vous ne pouvez pas poster sans approbation.
|
Connexion
Menu
Chercher WDForge
Chercher Web
Partenaires
|