Envoyé par
syrine01
Comment je veux découper le texte du fichiers en ligne (sur quel critère se base ).
Je ne comprends pas trop la question. On découpe déjà le fichier en ligne sur la base que le fichier contient des lignes, et qu'on le lit ligne par ligne.
C'est ce que fait cette ligne de code : List<String> lignes = Files.readAllLines(Paths.get("extractPdf.txt"));
Envoyé par
syrine01
De plus, le fusion de deux lignes s'il existe le mot " (Scored)" comment doit etre fait en java?
Sans parler de Java pour commencer, il suffit de réfléchir un peu. Reprenons ton exemple :
8.1.6 Record Events That Modify the System's Network
Environment (Scored)
Que remarque-t-on ? Un titre commence par un motif de type "une suite de nombres séparés par des .", ce qu'on a sélectionné jusqu'à maintenant avec : Pattern pattern = Pattern.compile("^((\\d+\\.)*?(\\d+)) .*$");Seulement, lorsque cette ligne ne contient ni (Scored) ni (Not Scored), on sait qu'on n'a pas le titre entier, n'est-ce-pas. Donc qu'il faut récupérer les lignes suivantes jusqu'à ce qu'on ait l'une de ces deux expression, et fusionner ces lignes pour en faire une seule (on peut garder les \n s'il faut, si on veut garder la structure multi-lignes du titre, si on a besoin).
La problématique, c'est qu'on va traiter une ligne, on va détecter que c'est un titre incomplet, puis on va lire les lignes suivantes, et tant qu'on a pas le titre complet, il faut les supprimer de la liste, et les concaténer au titre incomplet. Donc il semble évident qu'on ait besoin :
- de détecter les titres incomplets
- de savoir où ils se trouvent pour pouvoir les remplacer par le titre complet
- de savoir où se trouve les lignes qui le complètent
Détecter les titres incomplets, ça on sait faire, c'est ceux qui matchent la regexp et ne contiennent ni (Scored) ni (Not Scored). En Java :
pattern.matcher(ligne).matches() && !ligne.contains("(Scored)") && !ligne.contains("(Not Scored)")
Pour savoir où se trouve une ligne, il suffit de connaître son index dans la liste.
1 2 3 4 5 6 7 8 9
|
int titre=-1; // on utilise -1 pour indiquer qu'on n'a pas de titre
for(int i=0; i<lignes.size(); i++) {
if ( pattern.matcher(ligne).matches() && !ligne.contains("(Scored)") && !ligne.contains("(Not Scored)") ) {
titre = i; // on a détecter un titre incomplet, donc on stocke sa position
}
} |
Maintenant, quand titre n'est pas -1, on sait qu'on a un titre incomplet, donc dans la boucle, on va faire quelque chose de spécial : regarder si on trouve la fin du titre pour le complèter.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
int positiontitre=-1; // on utilise -1 pour indiquer qu'on n'a pas de titre
for(int i=0; i<lignes.size(); i++) {
if ( pattern.matcher(ligne).matches() && !ligne.contains("(Scored)") && !ligne.contains("(Not Scored)") ) {
positiontitre = i; // on a détecter un titre incomplet, donc on stocke sa position
}
else if ( positiontitre!=-1 ) { // on sait qu'on a un titre incomplet à complèter...
if ( ligne.contains("(Scored)") || ligne.contains("(Not Scored)") ) { // on détecte si on a la fin du titre
// ici on a la fin du titre, et on sait qu'il est en i
// donc maintenant on va regrouper toutes les lignes entre positiontitre et i, et on passera au titres suivants
}
}
} |
Pour regrouper les lignes entre positiontitre et i, il faut déjà les parcourir :
1 2
| for(int j=positiontitre; j<=i; j++) {
} |
Et donc il faut les concaténer. Pour faire ça on peut utiliser un StringBuilder :
1 2 3 4 5 6 7 8 9 10
| StringBuilder sb = new StringBuilder();
for(int j=positiontitre; j<=i; j++) {
if ( sb.length()>0 ) { // si on a déjà quelque chose dans le StringBuilder, on ajouter un retour chariot pour passer à la ligne
sb.append("\n");
}
sb.append(lignes.get(j));
}
String titrecomplet = sb.toString(); |
Si tu ne veux pas des passages à la ligne entre les différentes parties de ligne de titres, tu peux enlever le "if".
Et pour le remplacer dans la ligne :
lignes.set(positionTitre, titreComplet);
Maintenant, il faut supprimer les bouts qu'on a ajouté, c'est-à-dire les lignes entre positiontitre et i, sauf la première, puisque c'est le titre complet maitenant. Il suffit de parcourir les lignes et de les supprimer avec la méthode remove(index) de List.
Seulement, il y a une chose à laquelle il faut faire attention, c'est que quand on supprime une ligne, toutes celles qui suivent changent de positions, forcément. Si on supprime la ligne 100, la ligne 101 se retrouve en 100 ! Une façon simple de prendre en compte ça et de supprimer les lignes en partant de la dernière : comme supprimer une ligne ne change que ce qui se trouve après, et pas ce qui se trouve avant, on n'a plus ce problème quand on va de la fin vers le début.
Donc, on peut écrire :
1 2 3
| for(int j=i; j>positionTitre; j--) {
lignes.remove(j);
} |
De la même façon, comme on n'était entrain de traiter la ligne i, et que celle-ci n'existe plus, ni même certaines ligne avant, la boucle :
1 2
| for(int i=0; i<lignes.size(); i++) {
} |
va avoir un problème similaire, d'autant plus que pour boucler on va faire i++.
Par exemple, imagine que le titre incomplet soit en 100, que la ligne avec score soit en 102, on supprime donc 101 et 102, et la ligne 103 devient la ligne 101, alors que i vaut 102, et puis 103 lorsqu'on va boucler. Donc il faut décaler i pour pouvoir poursuivre correctement la boucle.
Le décaler simplement en arrière de façon à ce qu'on soit comme si on était entrain de traiter encore le titre. Donc de faire :
En reprendant l'exemple ci-avant, i va valoir 100. puis lorsqu'on va boucler, on va faire i++, i va valoir 101. Donc on va bien traiter la ligne suivante (celle qui suivait avant, celle qui avant était en 103).
Enfin, comme on fait un traitement particulier lorsque positiontitre!=-1 parce que çà veut dire qu'on est en train de traiter un titre incomplet, il ne faut plus le faire, puisque justement on a fini de traiter le titre incomplet, soit :
Donc en résumé :
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
| nt positiontitre=-1; // on utilise -1 pour indiquer qu'on n'a pas de titre
for(int i=0; i<lignes.size(); i++) {
if ( pattern.matcher(ligne).matches() && !ligne.contains("(Scored)") && !ligne.contains("(Not Scored)") ) {
positiontitre = i; // on a détecter un titre incomplet, donc on stocke sa position
}
else if ( positiontitre!=-1 ) { // on sait qu'on a un titre incomplet à complèter...
if ( ligne.contains("(Scored)") || ligne.contains("(Not Scored)") ) { // on détecte si on a la fin du titre
// ici on a la fin du titre, et on sait qu'il est en i
// donc maintenant on va regrouper toutes les lignes entre positiontitre et i, et on passera au titres suivants
StringBuilder sb = new StringBuilder();
for(int j=positiontitre; j<=i; j++) {
if ( sb.length()>0 ) { // si on a déjà quelque chose dans le StringBuilder, on ajouter un retour chariot pour passer à la ligne
sb.append("\n");
}
sb.append(lignes.get(j));
}
String titrecomplet = sb.toString();
lignes.set(positionTitre, titreComplet);
for(int j=i; j>positionTitre; j--) {
lignes.remove(j);
}
i=positionTitre;
positionTitre = -1;
}
}
} |
Maintenant on se retrouve bien avec un texte tels ques tous les titres sont dans un seul item de la liste, donc le code qui traitent item par item la liste va fonctionner sans avoir à le changer.
PS. au fait, j'ai relu l'un de tes derniers codes.... et y'a un truc que je n'avais pas remarqué. C'est quoi ce machin :
Pattern pattern2 = Pattern.compile("[0-9].*?.*[0-9].*$"); // récupérer toute la ligne qui contient par exemple 1.1 ..
?
ça sert à quoi ? A part à faire n'importe quoi ? Et certainement pas ce qui est écrit en commentaire
Parce que ta regexpl, elle cherche :
- un chiffre unique
- suivi de n'importe quel caractère un nombre quelconque de fois (de 0 à l'infini), mais en s'arrêntant au premier truc qui matche la suite
- suivi d'un chiffre unique
- suivi de n'importe quel caractère un nombre quelconque de fois (de 0 à l'infini)
- tout ça en fin de ligne
ça donne juste un truc qui ressemble à pas du n'importe quoi parce qu'on fait un matche sur une regexp qui elle est correcte : on a une ligne qui commence forcément par un chiffre et que se termine par des caractères, et qu'il y par hasard d'autres chiffres dedans qui sont bien séparés par aucun caractère entre (et encore si ton titre c'était juste "1. titre", et bien, ça ne fonctionnerait pas.
Mais c'est complètement inutile et surtout inutilement compliqué puisqu'on peut écrire :
maps.put(ligne, paragraphe);
pour faire la même chose. Et qu'en plus ce code a au moins du sens.
Partager