Word-File lesen, mit regulären Ausd. (regex) interpretieren

Davicito

Erfahrenes Mitglied
Ich bin gestern auf ein Problem gestoßen, wo ich in Moment selber nicht genau weiß, womit das zusammen hängen mag und möchte gerne einmal die Java-Forum-Gemeinde fragen, ob jemanden von Euch etwas bekannt wäre.

Vorhaben
Ich lese mit der Apache.poi-Bibliothek ein Word-Dokumte ein und versuche mit Hilfe von regulären Ausdrücken herauszufinden, ob eine Anschrift, Email-Adresse, Telefonnummer etc. enthalten sind. Dazu ein kleiner Quell-Code von mir (Aus dem Beitrag von Gestern: https://www.tutorials.de/threads/fr...n-regulaeren-ausdruecken.402407/#post-2076273):

Java:
...
public class Model{
    WordExtractor we = null;
    FileInputStream fis = null;
    HWPFDocument doc = null;
    
    String texContent;
  
    public Model(){}
  
    public void readFile(){
        try{
            fis = new FileInputStream("C:\\test.doc");
            doc = new HWPFDocument(fis);
            we = new WordExtractor(doc);
            fis.close();       
        }
        catch(Exception e){
            e.printStackTrace();
        }
             
        for(String para: we.getParagraphText()){          
            String[] tokens = para.split("[\\t:;, ]+");
            for(int i=0; i < tokens.length; i++){
               if(Pattern.matches("[Ee-]{1,2}?[Mm]ail", tokens[i]) &&
                        Pattern.matches("[a-zA-Z0-9-_]+@[a-zA-Z0-9-_]+\\.[a-z]{2,3}", tokens[i+1])){ 
                    System.out.print(tokens[i+1]);                     
                }
            }           
        }
    }
}

Ich lese im oberen Abschnitt (Zeilen 14-17) eine Word-Datei ein und versuche mit den entsprechenden regulären Ausdrücken (Zeile 26 - 29) nach Email-Adressen ausschau zu halten.

Zu Testzwecken habe ich eine Doc-Datei "test.doc" mit folgendem Inhalt erstellt:
Adresse Hochmeisterstr.3a
Anschrift: kei_der-dam-m- 23
Hallo World tabulator
Telefon 24567987
Das ist eine Word-Datei
Das ist eine weitere Zeile
E-Mail gehsj@jsd.com
lkjl

Problemfall
Wenn ich jetzt in der Schleife über den Index des String-Arrays "tokens" iteriere, werden mir alle Wörter, so wie sie in der Doc-Datei stehen, ausgegeben.
Auch wenn ich nur nach dem Key-Wort "E-mail" mit den regulären Ausdruck: Pattern.matches("[Ee-]{1,2}?[Mm]ail", tokens) suche, wird mir der Token auf der Konsole angezeigt, der das Word E-mail beinhaltet.
Mein Problem ist nun aber, dass die nachfolgende Email-Adresse "gehsj@jsd.com" (tokens[i+1]) nicht ausgegeben wird.

Analyse
Ich habe bereits Stunden gegoogelt und bisher auf nichts brauchbares gestoßen. Also habe ich selber versucht zu ergründen worin der Fehler bestehen könnte.
Zuerst habe ich gestern einen hilfreichen Tipp bekommen, das man auf der Seite: http://www.rubular.com/r/D8xmoDbgq6 seine reg. Ausdrücke überprüfen kann, um Fehler im Ausdruck ausschließen zu können. Mein regulärer Ausdruck habe ich also im Vorfeld getestet und ist korrekt!

Da ich also so nicht auf den Fehler ommen konnte, ist mir in den Sinn gekommen, ob die Ursache des Fehlers in Zusammenhang mit dem Format doc zu tun hätte.
Dazu habe ich schnell eine neue Klasse geschrieben die statt einer Doc-, eine Txt-Datei einließt.
Ich habe den identischen Inhalt der test.doc in die neue txt-Datei kopiert und mit dem selben Ausdruck geschaut, ob mir nun die Email-Adresse ausgegeben wird, und siehe da, es hat also geklappt.

Siehe Code-Beispiel:
Java:
public void readFile(){
        try{
           fr = new FileReader(new File("C:/test.txt"));
           br = new BufferedReader(fr);
           String zeile;
           while((zeile = br.readLine()) !=  null){
              String[] tokens = zeile.split("[\\t:;, ]+");
              for(int i=0; i < tokens.length; i++){
                 if(Pattern.matches("[Ee-]{1,2}?[Mm]ail", tokens[i]) &&
                        Pattern.matches("[a-zA-Z0-9-_]+@[a-zA-Z0-9-_]+\\.[a-z]{2,3}", tokens[i+1])){
                    System.out.print(tokens[i+1]);                     
                 }
              }           
           } 
           br.close();
        }
        catch(FileNotFoundException e){
            e.printStackTrace();
        }


Komisch ist auch das Phänomen, dass wenn in der Doc-Datei ein Hyperlink für Emails gesetzt wird, auch nichts mehr im Token-Platzhalter für die Email-Adresse steht (leer).

Wenn jemand ähnliche Erfahrungen gesammelt hat und vielleicht eine Lösung für mein Problem hätte, dem wäre ich sehr dankbar.
 
Zuletzt bearbeitet:

Davicito

Erfahrenes Mitglied
Java:
...
for(int i=0; i < tokens.length; i++){
                System.out.print(tokens[i]+", ");
}
...

Ausgabe aller Tokens:
Adresse, Hochmeisterstr.3a
, Anschrift, kei_der-dam-m-, 23
, Hallo, World, tabukator
, Telefon, 24567987
, Das, ist, eine, Word-Datei
, Das, ist, eine, weitere, Zeile
, E-Mail, gehsj@jsd.com
, lkjl
,
 

vfl_freak

Premium-User
Hä?? was heißt das jetzt genau ??? :eek:

Wie schaut denn der Inhalt des DOCs aus ??

Ist dies eine Zeile?
"E-Mail, gehsj@jsd.com"

Falls JA, dann sollte nach dem Splitten tokens so ausschauen:
Java:
tokens[0] = 2E-Mail"
tokens[1] = "gehsj@jsd.com"

dann matched dieser Code wunderbar:
Java:
String[] myText = { "E-Mail", "gehsj@jsd.com" };
if( Pattern.matches("[Ee-]{1,2}?[Mm]ail", myText[i]) && Pattern.matches("[a-zA-Z0-9-_]+@[a-zA-Z0-9-_]+\\.[a-z]{2,3}", myText[i+1]) )
{
    System.out.println( "match " + myText[i+1] );                   
}
else
{
    System.out.println( "nomatch " + myText[i+1] );
}

Deine for-Schleife ist dort wohl überfüssig, da es ja nur eine Zeile ist, die Du betrachtest und zudem gefährlich, da es am Ende durch das i+1 wohl immer zu einer "ArrayIndexOutOfBoundsException" kommen wird!

Gruß Klaus
 

Davicito

Erfahrenes Mitglied
Hä?? was heißt das jetzt genau ??? :eek:

Wie schaut denn der Inhalt des DOCs aus ??

Ist dies eine Zeile?
"E-Mail, gehsj@jsd.com"
....
Hi wie ich bereit oben geschrieben habe
...
Zu Testzwecken habe ich eine Doc-Datei "test.doc" mit folgendem Inhalt erstellt:
Adresse Hochmeisterstr.3a
Anschrift: kei_der-dam-m- 23
Hallo World tabulator
Telefon 24567987
Das ist eine Word-Datei
Das ist eine weitere Zeile
E-Mail gehsj@jsd.com
lkjl
....

Ich habe eine For-Schleife die zeilenweise String-Buffer erzeugt (mehrere Zeilen)
Java:
for(String zeilen: we.getParagraphText()){
    System.out.print(zeilen.toString());
}
Diesen String muss ich nun noch in Tokens teilen um eine Word-Analyse zu machen. also nicht auf eine Zeile bezogen, sondern auf einzelne Wörter.
Dazu setze ich ein String-Array "tokens" und trenne mit der split()-Methode aus jedem Zeilen-Stream (String-Buffer) alle Wörter die als Array eingelesen werden.

Anschließend möchte ich mir zum Test alle Tokens ausgeben lassen, die gewisse Konventionen (regex) erfüllen.
Java:
for(String zeilen: we.getParagraphText()){
    //System.out.print(zeilen.toString());
    String[] tokens = zeilen.split("[\\t.:;, ]+");
   
    for(int i=0; i < tokens.length; i++){
          System.out.print(tokens[i]+", ");

          /*Gefilterte Ausgabe durch reguläre Ausdrücke (regex)
          *   
          */  
    }
}
 

Davicito

Erfahrenes Mitglied
Java:
String[] myText = { "E-Mail", "gehsj@jsd.com" };
if( Pattern.matches("[Ee-]{1,2}?[Mm]ail", myText[i]) && Pattern.matches("[a-zA-Z0-9-_]+@[a-zA-Z0-9-_]+\\.[a-z]{2,3}", myText[i+1]) )
{
    System.out.println( "match " + myText[i+1] );                  
}
else
{
    System.out.println( "nomatch " + myText[i+1] );
}
...
Logischer Weise klappt Ihr Beispiel-Code wunder bar. Nur wenn die Quelle der Wörter aus einer Doc stammt, funktioniert das nicht mehr so wunderprächtig. Wenn aber die Quelle aus einer normalen txt-Datei kommt, gibt es keine Probleme weder mit meinem Quell-Code noch mit meinen Ausdrücken.
 

vfl_freak

Premium-User
Hmm, jetzt hast Du ja schon wieder geänderten Code gepostet ..... :mad:

Und dann alleine diese Aussage:
Ich habe eine For-Schleife die zeilenweise String-Buffer erzeugt (mehrere Zeilen)
Was nun?
zeilenweise?
mehrere Zeilen?
Wo sehe ich eine Stringbuffer?

Ich schrieb Dir gestern schon im anderen Beitrag, dass Dein regulärer Ausdruck völlig ok ist!
Das Problem liegt also im Inhalt von tokens !!

Nochmal: lauf im Debugger durch und schau was jeweils matcht ...
Gruß Klaus
 

vfl_freak

Premium-User
Nur wenn die Quelle der Wörter aus einer Doc stammt, funktioniert das nicht mehr so wunderprächtig. Wenn aber die Quelle aus einer normalen txt-Datei kommt, gibt es keine Probleme weder mit meinem Quell-Code noch mit meinen Ausdrücken.
Aha ... wenn es mit einer normalen Textdatei klappt (das hättest Du ja auch schon mal eher schreiben können!), ist doch klar, wo der Hund begraben!
Es liegt also doch am Inhalt von tokens ..... :confused:
 

Davicito

Erfahrenes Mitglied
Aha ... wenn es mit einer normalen Textdatei klappt (das hättest Du ja auch schon mal eher schreiben können!), ist doch klar, wo der Hund begraben!
Es liegt also doch am Inhalt von tokens ..... :confused:
Steht im Beitrag von Gestern, wie auch oben unter Analyse!
Das es an dem Inhalt liegt weiß ich auch... nur bringt mich das nicht weiter da ich den Inhalt ja auch mit einer Schleife von 0-n ausgeben kann. und ich sehe meine Mail-Adresse auch nur wieso klappt die Filterung nicht?
 

vfl_freak

Premium-User
na, weil vermutlich nicht das drin steht, was Du erwartest ..... :oops:
Wenn wenn es mit einer normalen Textdatei klappt, nur von Worddokument aus nicht, dann stehen dort im Text vielleicht noch spezielle Formatierungszeichen ö. ä. drin !!
Deswegen glaube ich auch nicht, dass Dein Text nur so ausschaut, wie oben im 3. Beitrag gepostet!

Da hier keiner die konkrete Worddatei kennt, kann ich Dir nur nochmals raten, das ganze mit im Debugger zu prüfen. Dort kannst Du Dir jedes einzelne Bit ausschauen !!

Ggf. ist es auch noch hilfreich, die beiden Prüfungen in der if-Bedingung
Java:
if( Pattern.matches("[Ee-]{1,2}?[Mm]ail", myText[i]) && Pattern.matches("[a-zA-Z0-9-_]+@[a-zA-Z0-9-_]+\\.[a-z]{2,3}", myText[i+1]) )
mal separat zu betrachten, daqmit Du weist, welche der beiden ggf. fehlschlägt !!

Gruß Klaus