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