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

Entrée/Sortie Java Discussion :

Taille lisible par un script Java inférieur à la taille du fichier


Sujet :

Entrée/Sortie Java

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    38
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 38
    Points : 33
    Points
    33
    Par défaut Taille lisible par un script Java inférieur à la taille du fichier
    Bonjour, je suis en train de réaliser un parseur de fichiers HTML pour extraire des informations d'une banque de fichiers HTML. J'ai créé un programme qui lit une liste de fichier et traite chaque fichier par ma fonction de parsing.

    Mon parseur lit des fichiers dont la taille varie entre 30ko et 250ko pour extraire des informations de la partie body du document qui tient sur une longue ligne.

    Pour faire ca j'utilise un scanner pour lire le fichier ligne par ligne. Jusque là tout va bien sauf que pour certains fichiers la lecture s'arrête au bout d'un certain nombre d'octets inférieur à la taille sans que je sache pourquoi.

    La taille tronquée est variable selon les fichiers.

    Ce phénomène est reproductible: si je relance le programme, ce sont toujours les même fichiers qui sont tronques et a la même taille.

    Mes autres logiciels ouvrent les fichiers sans problème.

    Utiliser un FileReader a la place ne change rien donc ça ne vient pas du scanner.

    Si j'ajoute des caractères avant l'endroit ou c'est tronqué le fichier tronqué fait toujours la même taille donc ça ne vient pas d'un caractère dans le fichier.

    J'ai essayé de renommer un fichier tronqué en me disant que l'ordre d'appel y était pour quelque chose et il a été lu complètement. Je lui ai remis son nom d'origine et il a été de nouveau tronque.

    Ps: je tourne sous windows vista avec eclipse 3.5 et java 6.0

    Voici le code de lecture ligne par ligne:
    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
     
    File f = new File(nomFichier)
    long tailleFichier = f.length();
     
    //lecture normale avec le scanner
    Scanner scanner = new Scanner(f, "UTF-8");
    if (scanner.hasNextLine()) {
    	String contenu = scanner.nextLine();
    	tailleLue = contenu.length();
    	System.out.println("lecture du fichier");
    while (scanner.hasNextLine()) {
    	contenu = scanner.nextLine();
    	tailleLue += contenu.length();
    }
     
    //s'il y a une erreur
    if (tailleLue < (tailleFichier - 24)) {
    //on ecrit dans le fichier de log des erreurs
    	erreurs.write(nomFichier + "\n taille lue:" + tailleLue
    			+ " Taille reelle " + tailleFichier + "\n");
    	try {
    //on essaie de lire plus loin avec un FileReader
    		Writer erreursFichier = new BufferedWriter(
    				new OutputStreamWriter(
    						new FileOutputStream(nomFichier
    								+ "ereurLecture.txt", true),
    						"UTF-8"));
    		erreursFichier.write(nomFichier + "\n taille lue:"
    				+ tailleLue + " Taille reelle "
    				+ tailleFichier + "\n");
    		erreursFichier.write("Derniere ligne :\n" + contenu
    				+ "\n");
     
    		try {
    			Reader r = new BufferedReader(new FileReader(
    					nomFichier));
     
    			char[] cbuf = new char[200];
    			int off = (int) tailleLue - 4;
    			int len = 200;
    			StringBuilder s = new StringBuilder();
    			s.append(contenu);
    			try {
    				while (r.read(cbuf, off, len) == 200) {
    					s.append(cbuf);
    				}
    			} catch (IndexOutOfBoundsException e4) {
    			} finally {
    				s.append(cbuf);
    			}
     
    			r.close();
    			erreursFichier.append('\n');
    			erreursFichier.append(s);
    		} catch (FileNotFoundException e3) {
    			e3.printStackTrace();
    		} catch (IOException e3) {
    			e3.printStackTrace();
    		}
    		erreursFichier.close();
    	} catch (FileNotFoundException e2) {
    		e2.printStackTrace();
    	} catch (IOException e2) {
    		e2.printStackTrace();
    	}
    } 
     
    scanner.close();
    Voici ce que j'ai comme tailles:

    taille lue:35897 Taille reelle 68226

    taille lue:68659 Taille reelle 155851

    taille lue:68647 Taille reelle 191998

    taille lue:35891 Taille reelle 174387

    taille lue:68657 Taille reelle 167987

    taille lue:19531 Taille reelle 38720

  2. #2
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,


    Scanner lit des caractères et non pas des octets !
    En UTF8 un caractère peut être stocké sur plusieurs octets...

    a++

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    38
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 38
    Points : 33
    Points
    33
    Par défaut
    Le problème ne se pose effectivement plus quand j'enlève le paramètre charset "UTF-8" de l'initialisation du scanner.

    Mais je pense qu'il ne vient pas de là puisque je demande d'ecrire la derniere chaine lue dans un fichier log et il manque y la fin quand je lis en mode "UTF-8" (pas de </body></html> et c'est tronque bien avant ces balises).

    De plus il y a peu de caractères non ascii (voire pas du tout) dans les fichiers que je parse et ça ne peut pas expliquer une difference de taille de 50%.

    En plus si j'ajoute des caractères ascii au fichier, la taille lue devrait augmenter et ce n'est pas le cas.

    Pour l'histoire de changement de nom c'est juste que ma liste de fichier n'est pas actualisee mais ca ne change rien au problème en fait.

  4. #4
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 552
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 552
    Points : 21 608
    Points
    21 608
    Par défaut
    Effectivement dans le cas présent le problème principal n'est pas la gestion du charset multibyte.

    Le problème est que tu comptes sur le fait que read() va toujours remplir le tableau. Ce n'est pas le cas. Tu ne dois pas arrêter si read() lit moins de 200 caractères.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    38
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 38
    Points : 33
    Points
    33
    Par défaut
    Effectivement Je n'avais pas vu ça mais ça ne changerait rien car dès la lecture du premier bloc j'ai une exception outofbound et le but du reader est plus de voir si par cette méthode j'arrive a lire plus loin dans le fichier qu'avec scanner (je me positionnne dans le fichier au dernier octet lu par le scanner) et ce n'est pas le cas.
    Heureusement d'ailleurs en un sens.

  6. #6
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    tu peux nous attacher un exemple de fichier qui déconne (j'ai bien dit "attacher" pas copier / coller!)

    Aussi, comme bien stipulé dans la doc, le scanner assume avoir atteint la fin lorsque qu'il recois du Readable derrière une IOException. Peux-tu donc nous donner, après ta boucle, ce qui se trouve dans scanner.ioException() ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    if (scanner.ioException()!=null)
        scanner.ioException().printStackTrace();
    Je gage que, quelque part dans le fichier, se trouve une suite de byte non conforme à l'UTF-8, ce qui déclenche une Exception et, a forciori, l'arrêt du scanner.


    PS/ jsute pour lire des lignes, les bufferedReader est bien plus efficace et facile à gérer que le scanner.

  7. #7
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    38
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 38
    Points : 33
    Points
    33
    Par défaut
    OK ca a resolu mon probleme, c'est effectivement une exception due à un caractère invalide. Du coup j'ai modifié mon reader pour qu'il continue la lecture en mode ansi.

    Merci

    Voici le code de l'exception pour ceux que ca peut interesser

    java.nio.charset.MalformedInputException: Input length = 1
    at java.nio.charset.CoderResult.throwException(Unknown Source)
    at sun.nio.cs.StreamDecoder.implRead(Unknown Source)
    at sun.nio.cs.StreamDecoder.read(Unknown Source)
    at java.io.Reader.read(Unknown Source)
    at java.util.Scanner.readInput(Unknown Source)
    at java.util.Scanner.findWithinHorizon(Unknown Source)
    at java.util.Scanner.hasNextLine(Unknown Source)

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 22/04/2014, 11h36
  2. Réponses: 1
    Dernier message: 04/05/2012, 13h49
  3. Réponses: 3
    Dernier message: 26/04/2012, 16h55
  4. Réponses: 2
    Dernier message: 17/06/2011, 10h04
  5. remplacer Scripted DataSet par une classe Java
    Par doria_serine dans le forum BIRT
    Réponses: 8
    Dernier message: 02/09/2009, 11h40

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