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 Perl Discussion :

Problème de lecture d'un fichier texte


Sujet :

Langage Perl

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    1 606
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 606
    Par défaut Problème de lecture d'un fichier texte
    Hello,

    lire un fichier au format txt, je sais faire mais là, le truc incompréhensible

    J'ai un fichier au format texte donc et dont chaque ligne doit commencer par la chaîne "XS" suivie de numéros et caractères. Des anomalies font que dans ce même fichier, je peux avoir des lignes qui ne commencent pas par cette chaîne. Celà est dû à des retours chariots qui ne devraient pas avoir lieu d'être.

    Le but de mon script (jetable) était au départ de chercher les lignes en anomalie et de les afficher.

    Le soucis, c'est que ce code là ne m'indique aucune anomalie :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    use strict;
    use warnings;
     
    my $fic = "resultat.txt";
    open(IN, "$fic") or die("err lecture $fic : $!\n");
    while(<IN>)
    {
    	chomp();
    	if ($_ !~ /^XS/)
    	{
    		warn "erreur : $_\n";
    	}
    }
    Comme dit, c'est du code jetable. Avouez qu'il n'y a rien de terrible là dedans !

    Sous mon éditeur de texte du boulot (Textpad), j'ai des dizaines de lignes qui ressortent en anomalie dans le fichier. Or, le code montré ci-dessus ne renvoie aucun warning alors que je lui demande justement de m'afficher les lignes qui ne commencent pas par "XS".

    J'utilise Perl v5.8.8 build 822 sous Windows XP.

    Quelqu'un peut-il me dire où se cache mon erreur ? Perso, je ne la trouve pas !

  2. #2
    Membre Expert
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    1 606
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 606
    Par défaut
    Je viens de faire un test, l'hallucination totale !!!

    Je sais que dans le fichier txt, il y a une ligne commençant par un espace, j'ai donc rajouté un warn dans ma boucle while :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    warn "erreur : $_\n" if ($_ =~/^ /);
    Devinez quoi ? Pas de warn qui s'affiche.

  3. #3
    Membre Expert
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    1 606
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 606
    Par défaut
    2ème test : j'ai ouvert ce fichier txt sous Excel, puis copy/paste dans TextPad pour le sauvegarder en tant que nouveau fichier txt.

    Et en faisant pointer mon script jetable sur ce nouveau fichier, là ça fonctionne.



    Le soucis dans l'histoire, c'est que le fichier txt est automatiquement généré par un SGBD et que j'ai un script à faire de grande envergure.

    Là pour mes tests, j'ai bossé sur un échantillon (9.000 enregistrements), environ 7 Mo au format txt donc copier/coller sous Excel, pas de soucis. Mais par la suite, mon futur script est censé travailler avec un fichier d'environ 130.000 lignes.

  4. #4
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 822
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 822
    Par défaut
    tu peux me l'envoyer ton fichier que je test de mon coté

  5. #5
    Membre Expert
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    1 606
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 606
    Par défaut
    Navré, il s'agit de données de type confidentiel

    3ème test effectué : je compare avec TextPad le fichier txt d'origine avec le second passé sous la moulinette d'Excel : fichiers identiques !!!

    Pourquoi alors Perl n'est-il pas capable de lire et comprendre le premier ?

  6. #6
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 822
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 822
    Par défaut
    c pas une histoire de caractere utf8 ou autre? et ton editeur doit le convertir automatiquement quand tu fais un copié / collé

  7. #7
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 822
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 822
    Par défaut
    voici un code de GLdavid pris dans les snippet, je sais pas si ça peut t'aider.
    c'est pour passer de utf-8 <=> iso-8859-1
    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
     
    #!/usr/bin/perl -w
     
    use strict;
    use Locale::Recode;
     
    sub to_iso {
    	my($file) = $_[0];
    	my($file_dest) = $file.".new";
    	open FICHIER, "< $file" or die "$!\n";
    	open FICHIER_DEST, ">> $file_dest" or die "$!\n";
    	while(<FICHIER>){
    		my($cd) = Locale::Recode->new(from => 'UTF-8',
    		to=>'ISO-8859-1');
    		die $cd->getError if $cd->getError;
    		$cd->recode($_) or die $cd->getError;
    		print FICHIER_DEST;			
    	}
    	close FICHIER and close FICHIER_DEST;
    	unlink $file and rename($file_dest, $file) and unlink $file_dest;
    }
     
    sub to_utf {
    	my($file) = $_[0];
    	my($file_dest) = $file.".new";
    	open FICHIER, "< $file" or die "$!\n";
    	open FICHIER_DEST, ">> $file_dest" or die "$!\n";
    	while(<FICHIER>){
    		my($cd) = Locale::Recode->new(from => 'ISO-8859-1',
    		to=>'UTF-8');
    		die $cd->getError if $cd->getError;
    		$cd->recode($_) or die $cd->getError;
    		print FICHIER_DEST;			
    	}
    	close FICHIER and close FICHIER_DEST;
    	unlink $file and rename($file_dest, $file) and unlink $file_dest;
    }
     
    sub recode_file {
    	my($file) = $_[0];
    	my($file_dest) = $file.".new";
    	my($encode) = $_[1];
    	if($encode eq "1"){
    		&to_iso($file, $file_dest);
    	}
    	else {
    		&to_utf($file, $file_dest);
    	}
    }
     
    sub recode_repertory {
    	my($repertory) = $_[0];
    	my($pos) = rindex($repertory, '/');
    	if($pos != (length($repertory)-1)){
    		$repertory .= '/';
    	}
    	my($encode) = $_[1];
    	chdir $repertory;
    	my(@files) = `ls`;
    	my($file);
    	foreach $file (@files){
    		$file = $repertory.$file;
    		chomp $file;
    		if( -f $file){
    			&recode_file($file, $encode);
    		}
    		elsif ( -d $file){
    			&recode_repertory($file, $encode);
    		}
    	}
    }
     
     
    ###################MAIN######################
     
     
    if ($#ARGV > -1){
    	chomp $ARGV[0] and chomp $ARGV[1];
    	if ($ARGV[0] =~ /[A-Za-z]+/){
    		print "recode prend 2 arguments.\n";
    		print "Le premier argument doit être un nombre :\n";
    		print "1 : UTF-8 => ISO-8859-1\n";
    		print "2 : ISO-8859-1 => UTF-8\n";
    		print "Le deuxième argument doit être le chemin absolu d'un fichier ou d'un répertoire.\n";
    		exit 0;
    	}
    	if ($ARGV[0] > 2 or $ARGV[0] < 1){
    		print "Le premier argument doit être un nombre valide :\n";
    		print "1 : UTF-8 => ISO-8859-1\n";
    		print "2 : ISO-8859-1 => UTF-8\n";
    		exit 0;
    	}
    	if ( -f $ARGV[1]){
    		&recode_file($ARGV[1], $ARGV[0]);	
    	}
    	elsif ( -d $ARGV[1]){
    		&recode_repertory($ARGV[1], $ARGV[0]);
    	}
    } 
    elsif ($#ARGV > 1) {
    	print "recode prend 2 arguments.\n";
    	print "Le premier argument doit être un nombre :\n";
    	print "1 : UTF-8 => ISO-8859-1\n";
    	print "2 : ISO-8859-1 => UTF-8\n";
    	print "Le deuxième argument doit être le chemin absolu d'un fichier ou d'un répertoire.\n";
    	exit 0;
    }
    elsif ($#ARGV == 0) {
    	print "recode prend 2 arguments.\n";
    	print "Le premier argument doit être un nombre :\n";
    	print "1 : UTF-8 => ISO-8859-1\n";
    	print "2 : ISO-8859-1 => UTF-8\n";
    	print "Le deuxième argument doit être le chemin absolu d'un fichier ou d'un répertoire.\n";
    	exit 0;
    }
    else {
    	print "recode prend 2 arguments.\n";
    	print "Le premier argument doit être un nombre :\n";
    	print "1 : UTF-8 => ISO-8859-1\n";
    	print "2 : ISO-8859-1 => UTF-8\n";
    	print "Le deuxième argument doit être le chemin absolu d'un fichier ou d'un répertoire.\n";
    	exit 0;
    }

  8. #8
    Expert confirmé
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Par défaut
    Citation Envoyé par Arioch Voir le message
    Sous mon éditeur de texte du boulot (Textpad), j'ai des dizaines de lignes qui ressortent en anomalie dans le fichier. Or, le code montré ci-dessus ne renvoie aucun warning alors que je lui demande justement de m'afficher les lignes qui ne commencent pas par "XS".
    [Mode="On sait jamais, des fois que..."]
    Tu es sûr que ce n'est pas seulement parce que tu as activé le wrapping du texte dans TextPad (passage à la ligne automatique) ??
    [/Mode]

    Sinon sans le fichier, je ne sais quoi te dire... Essaie de vérifier qu'il n'y a pas de caractères incongrus et invisibles dedans, SciTE fait ça très bien : tu peux lui demander de t'afficher tous les caractères de contrôle et les espaces et fins de lignes.

    --
    Jedaï

  9. #9
    Membre Expert
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    1 606
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 606
    Par défaut
    Citation Envoyé par Jedai Voir le message
    [Mode="On sait jamais, des fois que..."]
    Tu es sûr que ce n'est pas seulement parce que tu as activé le wrapping du texte dans TextPad (passage à la ligne automatique) ??[/Mode]
    En fait, j'ai trouvé : lorsqu'un enregistrement est lu sur 2 lignes dans le fichier (une anomalie), le caractère terminant la première ligne n'est ni"\r\n", ni "\n" mais il provoque bien sous TextPad, SciTE, notepad, wordpad, word un retour à la ligne. Idem sous Excel ou le Writer d'OpenOffice.

    Lorsque je fais une recherche sur ce caractère de fin de ligne, TextPad par exemple le tope comme un vulgaire "\n", Perl non.

    Je n'aime pas utiliser chop au lieu de chomp mais demain, j'essaie de "choper" les lignes du fichier et voir si je peux enfin en exploiter les données.

    Citation Envoyé par Jedai Voir le message
    Sinon sans le fichier, je ne sais quoi te dire... Essaie de vérifier qu'il n'y a pas de caractères incongrus et invisibles dedans, SciTE fait ça très bien : tu peux lui demander de t'afficher tous les caractères de contrôle et les espaces et fins de lignes.
    SciTE ne voit aucun caractère étrange dans le fichier, on voit bien du texte à l'écran mais effectivement, je ne lui ai pas demandé d'afficher les caractères invisibles. J'essaie demain, une piste à creuser !

  10. #10
    Membre Expert
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    1 606
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 606
    Par défaut
    Jedai, le coup d'afficher les caractères invisibles sous SciTE a donné ceci :

    - certaines lignes sont terminées par CR LF, quasi presque toutes.
    - d'autres lignes sont terminées par CR uniquement.
    - et là, étrange : une quinzaine d'autres n'ont aucun caractère visible de retour à la ligne mais le retour à la ligne est bel et bien visible dans le fichier sous SciTE.

    J'ai rajouté ceci dans mon script Perl, à l'intérieur de la boucle while qui lit les lignes, une à une :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    warn "ligne $. termine par \\r\n" if (/\r$/);
    warn "ligne $. termine par \\r\\n\n" if (/\r\n$/);
    warn "ligne $. termine par \\n\n" if (/\n$/);
    Le warn ne renvoie absolument rien pour les 2 premiers cas de figure. Par contre, il ne renvoie que le 3è cas.

    Je teste avec chop et non chomp à présent pour voir ce qui se passe.

  11. #11
    Expert confirmé
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Par défaut
    Au lieu d'utiliser \n et \r qui ont des significations un peu magiques en Perl, utilise plutôt directement \013 et \015 (ou un truc comme ça), et lis ton fichier en mode binaire ('<:raw').

    - et là, étrange : une quinzaine d'autres n'ont aucun caractère visible de retour à la ligne mais le retour à la ligne est bel et bien visible dans le fichier sous SciTE.
    Tu es bien certain que tu n'as pas activé le wrapping ?

    --
    Jedaï

  12. #12
    Membre Expert
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    1 606
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 606
    Par défaut
    Citation Envoyé par Jedai Voir le message
    Tu es bien certain que tu n'as pas activé le wrapping
    Oui, certain.

Discussions similaires

  1. Problème de lecture dans un fichier texte.
    Par Mike888 dans le forum C
    Réponses: 3
    Dernier message: 24/05/2007, 11h45
  2. [WIN32]problème de Lecture d'un fichier texte
    Par jesus144 dans le forum Windows
    Réponses: 14
    Dernier message: 23/02/2007, 11h40
  3. problème de lecture depuis un fichier texte
    Par [Hugo] dans le forum C++
    Réponses: 12
    Dernier message: 27/10/2006, 16h46
  4. [VBnet] Problème de lecture d'un fichier texte.
    Par dibeloni dans le forum Windows Forms
    Réponses: 3
    Dernier message: 31/03/2006, 19h12
  5. Réponses: 2
    Dernier message: 28/12/2005, 15h00

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