2012-04-20 18 views
11

Le stringhe che sto utilizzando (a livello di codice) dai file MS Word quando si utilizza POI Apache non sono lo stesso testo che posso visualizzare quando apro i file con MS Word.Java: POI Apache: posso ottenere testo pulito dai file MS Word (.doc)?

Quando si utilizza il seguente codice:

File someFile = new File("some\\path\\MSWFile.doc"); 
InputStream inputStrm = new FileInputStream(someFile); 
HWPFDocument wordDoc = new HWPFDocument(inputStrm); 
System.out.println(wordDoc.getText()); 

l'uscita è una sola linea con molti personaggi 'non valide' (sì, le 'scatole'), e molte stringhe indesiderati, come "FORMTEXT", "HYPERLINK \l "_Toc##########" "('#' essere cifre numeriche)," PAGEREF _Toc########## \h 4", ecc

il seguente codice 'fissa' il problema a linea singola, ma mantiene tutti i caratteri non validi e testo indesiderato:

File someFile = new File("some\\path\\MSWFile.doc"); 
InputStream inputStrm = new FileInputStream(someFile); 
WordExtractor wordExtractor = new WordExtractor(inputStrm); 
for(String paragraph:wordExtractor.getParagraphText()){ 
    System.out.println(paragraph); 
} 

Non so se sto usando il metodo sbagliato per estrarre il testo, ma questo è quello che ho trovato quando ho visto POI's quick-guide. Se lo sono, qual è l'approccio corretto?

Se l'output è corretto, esiste un metodo standard per eliminare il testo indesiderato o devo scrivere un filtro personale?

risposta

6

Ci sono due opzioni, una fornita direttamente nel POI Apache, l'altra tramite Apache Tika (che utilizza POI Apache internamente).

La prima opzione è quella di utilizzare WordExtractor, ma con una chiamata al numero stripFields(String) quando si chiama. Ciò rimuoverà i campi basati sul testo inclusi nel testo, cose come HYPERLINK che hai visto. Il tuo codice sarebbe diventato:

NPOIFSFileSystem fs = new NPOIFSFileSytem(file); 
WordExtractor extractor = new WordExtractor(fs.getRoot()); 

for(String rawText : extractor.getParagraphText()) { 
String text = extractor.stripFields(rawText); 
System.out.println(text); 
} 

L'altra opzione è quella di utilizzare Apache Tika. Tika fornisce l'estrazione del testo e i metadati per un'ampia varietà di file, quindi lo stesso codice funzionerà per .doc, .docx, .pdf e molti altri. Per ottenere pulito, testo normale del documento di Word (è anche possibile ottenere XHTML se si preferisce), devi fare qualcosa di simile:

TikaConfig tika = TikaConfig.getDefaultConfig(); 
TikaInputStream stream = TikaInputStream.get(file); 
ContentHandler handler = new BodyContentHandler(); 
Metadata metadata = new Metadata(); 
tika.getParser().parse(input, handler, metadata, new ParseContext()); 
String text = handler.toString(); 
+2

La seconda soluzione non ha funzionato in i miei test TIKA-1.2 ha restituito FORMCHECKBOX e altre cose dai file .doc. File .docx ha funzionato bene però. – Simon

+0

Ti suggerisco di provare con la versione più recente di Tika, 1.3. Se il problema si verifica ancora lì, si prega di [sollevare un bug] (https://issues.apache.org/jira/browse/TIKA) e caricare un file di esempio mostrandolo, in modo che possiamo indagare! – Gagravarr

+0

Questo succede ancora in Tika 1.3 per me, per quello che vale. – damd

7

Questa classe in grado di leggere sia i file .doc e .docx in Java . Per questo sto usando tika-app-1.2.jar:

/* 
* This class is used to read .doc and .docx files 
* 
* @author Developer 
* 
*/ 

import java.io.ByteArrayOutputStream; 
import java.io.File; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.io.OutputStreamWriter; 
import java.net.URL; 
import org.apache.tika.detect.DefaultDetector; 
import org.apache.tika.detect.Detector; 
import org.apache.tika.io.TikaInputStream; 
import org.apache.tika.metadata.Metadata; 
import org.apache.tika.parser.AutoDetectParser; 
import org.apache.tika.parser.ParseContext; 
import org.apache.tika.parser.Parser; 
import org.apache.tika.sax.BodyContentHandler; 
import org.xml.sax.ContentHandler; 

class TextExtractor { 
    private OutputStream outputstream; 
    private ParseContext context; 
    private Detector detector; 
    private Parser parser; 
    private Metadata metadata; 
    private String extractedText; 

    public TextExtractor() { 
     context = new ParseContext(); 
     detector = new DefaultDetector(); 
     parser = new AutoDetectParser(detector); 
     context.set(Parser.class, parser); 
     outputstream = new ByteArrayOutputStream(); 
     metadata = new Metadata(); 
    } 

    public void process(String filename) throws Exception { 
     URL url; 
     File file = new File(filename); 
     if (file.isFile()) { 
      url = file.toURI().toURL(); 
     } else { 
      url = new URL(filename); 
     } 
     InputStream input = TikaInputStream.get(url, metadata); 
     ContentHandler handler = new BodyContentHandler(outputstream); 
     parser.parse(input, handler, metadata, context); 
     input.close(); 
    } 

    public void getString() { 
     //Get the text into a String object 
     extractedText = outputstream.toString(); 
     //Do whatever you want with this String object. 
     System.out.println(extractedText); 
    } 

    public static void main(String args[]) throws Exception { 
     if (args.length == 1) { 
      TextExtractor textExtractor = new TextExtractor(); 
      textExtractor.process(args[0]); 
      textExtractor.getString(); 
     } else { 
      throw new Exception(); 
     } 
    } 
} 

da compilare:

javac -cp ".:tika-app-1.2.jar" TextExtractor.java 

Per eseguire:

java -cp ".:tika-app-1.2.jar" TextExtractor SomeWordDocument.doc 
3

Prova questa, funziona per me ed è puramente una soluzione POI. Dovrai cercare la controparte HWPFDocument però. Assicurati che il documento che stai leggendo sia precedente a Word 97, altrimenti usa XWPFDocument come faccio io.

InputStream inputstream = new FileInputStream(m_filepath); 
//read the file 
XWPFDocument adoc= new XWPFDocument(inputstream); 
//and place it in a xwpf format 

aString = new XWPFWordExtractor(adoc).getText();   
//gets the full text 

Ora, se volete alcune parti è possibile utilizzare la getparagraphtext ma non utilizzate l'estrattore di testo, utilizzare direttamente sul punto come questo

for (XWPFParagraph p : adoc.getParagraphs()) 
{ 
    System.out.println(p.getParagraphText()); 
}