Sujet : création d'une liste de fréquences de mots
/* * Projet de rattrapage 1er semestre - Liste de fréquences de mots dans un texte */ package fr.crim.a2012.freqlist; import java.io.File; import java.io.IOException; /** * Contrat pour un outil élémentaire de statistiques lexicales * * @author Frédéric GLORIEUX * @author Pierre DITTGEN */ public interface FreqList { /** * Charger un fichier texte */ void lit(File f) throws IOException; /** * Donner une liste des n mots les plus fréquents (un par ligne), * selon le format "mot,fréquence" */ void afficheTetes(int n); }
/* * Projet de rattrapage 1er semestre - Liste de fréquences de mots dans un texte */ package fr.crim.a2012.freqlist; import java.io.File; import java.io.IOException; import java.util.HashSet; import java.util.Scanner; import java.util.Set; /** * Une classe abstraite qui traite la lecture du fichier d'entrée * * @author Frédéric Glorieux * @author Pierre Dittgen */ public abstract class AbstractFreqlist implements FreqList { /** Ensemble de mots vides, i.e. à ne pas prendre en compte à la lecture. */ private Set<String> lesMotsVides = new HashSet<String>(); /** * Constructeur. * Charge la liste de mots vides à partir du fichier rsc/fr.stop * * @throws IOException en cas d'erreur lors de la lecture du fichier de * mots vides */ public AbstractFreqlist() throws IOException { // Charger la liste des mots vides Scanner scan = new Scanner(new File("rsc/fr.stop"), "UTF-8"); String ligne; while (scan.hasNextLine()) { ligne = scan.nextLine().trim(); if (ligne.isEmpty() || ligne.charAt(0) == '#') { continue; } lesMotsVides.add(ligne); } } /** * Cette méthode lit le contenu du fichier passé en paramètre. Pour chaque * mot non vide rencontré, elle appelle la méthode mot() * @param f Le fichier à lire * @see #mot(String) * @throws IOException En cas d'erreur durant la lecture du fichier */ @Override public void lit(File f) throws IOException { Scanner scan = new Scanner(f, "UTF-8"); // séparateur, tout ce qui n'est pas lettre selon l'unicode scan.useDelimiter("\\P{L}+"); String mot; while (scan.hasNext()) { mot = scan.next().toLowerCase(); if (mot.isEmpty() || lesMotsVides.contains(mot)) { continue; } mot(mot); } } /** * Méthode appelée chaque fois qu'un mot non vide est lu dans le fichier * d'entrée. Cette méthode affiche le mot lu. * Il est nécessaire de surcharger cette méthode pour la stocker dans * une liste de fréquences * @param mot le mot lu */ protected void mot(String mot) { System.out.println(mot); } /** * Tester une implémentation de liste de fréquences * @param impl une instance de classe implémentant l'interface FreqList */ static public void test(FreqList impl) throws IOException { // Lit la société du spectable de Guy Debord impl.lit(new File("rsc/debord_spectacle.txt")); // Affiche les 20 mots plus fréquents par fréquence décroissante System.out.println("Les 20 mots les plus fréquemment rencontrés dans le texte :"); impl.afficheTetes(20); } }
/* * Projet de rattrapage 1er semestre - Liste de fréquences de mots dans un texte */ package fr.crim.a2012.freqlist; import java.io.IOException; import java.util.Arrays; import java.util.HashMap; import java.util.Map; /** * Implémentation * @author Frédéric Glorieux */ public class FgFreqlist extends AbstractFreqlist { /** Pour stocker les fréquences des mots */ private Map<String,Integer> dico = new HashMap<String,Integer>(); /** * Constructeur * @throws Exception */ public FgFreqlist() throws IOException { super(); } @Override public void mot(String mot) { if (dico.containsKey(mot)) { dico.put(mot, new Integer(dico.get(mot)+1)); } else { dico.put(mot, new Integer(1)); } } @Override public void afficheTetes(int n) { Forme[] liste = new Forme[dico.size()]; int i = 0; for (String forme : dico.keySet()) { liste[i] = new Forme(forme, dico.get(forme)); i++; } Arrays.sort(liste); for (i=0; i<n; i++) { System.out.println(liste[i]); } } /** * Tester les méthodes abstraites partagées */ public static void main(String[] args) throws Exception { AbstractFreqlist.test(new FgFreqlist()); } /** * Un objet qui combine le terme et sa fréquence */ public class Forme implements Comparable<Forme> { private String mot; private int compte; public Forme(String mot, int compte) { this.mot = mot; this.compte = compte; } public String getMot() { return mot; } public int getCompte() { return compte; } public String toString() { return mot+","+compte; } @Override public int compareTo(Forme o) { return o.getCompte()-this.getCompte(); } } }
SAX et DOM : deux API standardisées pour l'accès aux documents XML
Donner la liste des événements émis lors de l'analyse de ce document par un parseur SAX :
<?xml version="1.0"?> <menu date="2013-23-10"> <entree>œufs mayonnaise</entree> <plat><viande>jambon</viande> <legume>coquillettes</legume></plat> <dessert>crème caramel</dessert> </menu>
Créer une classe héritant de DefaultHandler :
public class MyHandler extends DefaultHandler { ...
Analyser un document XML en utilisant notre handler personnalisé :
MyHandler handler = new MyHandler(); SAXParserFactory spf = SAXParserFactory.newInstance(); // pour éviter la validation de la DTD spf.setValidating(false); spf.setFeature("http://xml.org/sax/features/validation", false); // Création de l'instance de parser SAXParser saxParser = spf.newSAXParser(); // Et analyse d'un fichier en utilisant le handler personnalisé saxParser.parse("rsc/monfichier.xml", handler);
La classe fr.crim.saxigraph.SAXWordCount développée lors de la séance du 09/01/2013 affiche les différentes balises trouvées dans le document XML analysé et pour chaque balise, le nombre d'occurrences rencontrées.
Résultats sur le texte étudié (encodé en TEI) :
p,2084 said,631 hi,116 div,47 pb,47 measure,4 date,2 title,2 bibl,2 body,1 creation,1 anchor,1 author,1 titleStmt,1 extent,1 TEI,1 sourceDesc,1 profileDesc,1 publicationStmt,1 note,1
Créer un fichier rsc/menu.xml avec le contenu suivant :
<?xml version="1.0"?> <menu date="2013-23-10"> <entree>œufs mayonnaise</entree> <plat><viande>jambon</viande> <legume>coquillettes</legume></plat> <dessert>crème caramel</dessert> </menu>
Modifier la classe pour afficher seulement le contenu texte de la balise <plat>
État de la classe en fin de séance :
/* * Cours Java / POO * M2 Pro Ingénierie Multilingue * INALCO */ package fr.crim.a2012.saxigraph; import java.io.IOException; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; /** * Une spécialisation de la classe DefaultHandler qui affiche sur la sortie * standard le contenu texte des balises <plat> * * @author Pierre DITTGEN */ public class SAXFrequence extends DefaultHandler { private StringBuilder text = new StringBuilder(); private boolean dansPlat; /** * Méthode appelée sur la lecture de contenu texte */ @Override public void characters(char[] ch, int start, int length) { if (dansPlat) { text.append(ch, start, length); } } /** * Méthode appelée sur une balise ouvrante */ @Override public void startElement(String uri, String localName, String qName, Attributes attrs) { if ("plat".equals(localName)) { dansPlat = true; // Remet le contenu du string builder à 0 text.setLength(0); } } /** * Méthode appelée sur une balise fermante */ @Override public void endElement(String uri, String localName, String qName) { if ("plat".equals(localName)) { dansPlat = false; System.out.println(text); } } /** * Méthode principale * @param args paramètres de la ligne de commande (ignorés) * @throws SAXException En cas de XML non valide * @throws ParserConfigurationException Peu probable * @throws IOException Si le fichier XML n'est pas trouvé par exemple */ public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException { SAXParserFactory spf = SAXParserFactory.newInstance(); spf.setNamespaceAware(true); spf.setValidating(false); spf.setFeature("http://xml.org/sax/features/validation", false); SAXParser saxParser = spf.newSAXParser(); saxParser.parse("rsc/menu.xml", new SAXFrequence()); } }
Anonymous
Pour la prochaine séance (30/01/2013)
Liste de mots vides