2012-04-20 29 views
11

Las cadenas que obtengo (mediante programación) de archivos de MS Word cuando uso Apache POI no son el mismo texto que puedo ver cuando abro los archivos con MS Word.Java: PDI de Apache: ¿Puedo obtener un texto limpio de los archivos de MS Word (.doc)?

Cuando se utiliza el siguiente código:

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

la salida es una sola línea con muchos personajes no válidos '(sí, las 'cajas'), y muchas cadenas no deseados, como "FORMTEXT", "HYPERLINK \l "_Toc##########" "('#' siendo dígitos numéricos)," PAGEREF _Toc########## \h 4", etc.

el siguiente código 'fija' el problema de una sola línea, pero mantiene todos los caracteres no válidos y texto no deseado:

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); 
} 

No sé si estoy utilizando el método incorrecto para extraer el texto, pero eso es lo que he encontrado al mirar POI's quick-guide. Si lo soy, ¿cuál es el enfoque correcto?

Si esa salida es correcta, ¿hay una forma estándar para deshacerse del texto no deseado, o tendré que escribir mi propio filtro?

Respuesta

6

Hay dos opciones, una proporcionada directamente en Apache POI, la otra a través de Apache Tika (que utiliza Apache POI internamente).

La primera opción es usar WordExtractor, pero envuélvala en una llamada al stripFields(String) al llamarlo. Eso eliminará los campos basados ​​en texto incluidos en el texto, cosas como HYPERLINK que has visto. Su código se convertiría en:

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); 
} 

La otra opción es utilizar Apache Tika. Tika proporciona extracción de texto y metadatos para una amplia variedad de archivos, por lo que el mismo código funcionará para .doc, .docx, .pdf y muchos otros también. Para conseguir limpia, texto plano del documento de Word (también se puede obtener XHTML si prefieres), que haría algo como:

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 segunda solución no funcionaba en mis pruebas TIKA-1.2 devolvió FORMCHECKBOX y otras cosas desde archivos .doc. Sin embargo, los archivos .docx funcionaron bien. – Simon

+0

Sugiero que intentes con la versión más reciente de Tika, 1.3. Si el problema persiste allí, por favor [presente un error] (https://issues.apache.org/jira/browse/TIKA) y cargue un archivo de muestra que lo muestre, para que podamos investigarlo. – Gagravarr

+0

Esto todavía sucede en Tika 1.3 para mí, por lo que vale. – damd

7

Esta clase puede leer archivos .doc y .docx tanto en Java . Para ello estoy 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(); 
     } 
    } 
} 

Recopilar:

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

Para ejecutar:

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

probar esto, funciona para mí y es puramente una solución de POI. Sin embargo, deberá buscar la contraparte HWPFDocument. Asegúrese de que el documento que está leyendo sea anterior a Word 97, de lo contrario use XWPFDocument como yo.

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 

Ahora, si quieres ciertas partes que puede utilizar el getparagraphtext pero no utiliza el extractor de texto, utilizarla directamente en el párrafo como éste

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