2012-04-20 52 views
11

Các chuỗi tôi (lập trình) nhận được từ các tệp MS Word khi sử dụng Apache POI không phải là cùng một văn bản mà tôi có thể xem khi mở tệp bằng MS Word.Java: Apache POI: Tôi có thể nhận được văn bản sạch từ các tệp MS Word (.doc) không?

Khi sử dụng đoạn mã sau:

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

đầu ra là một dòng duy nhất với nhiều nhân vật 'không hợp lệ' (vâng, 'chiếc hộp'), và nhiều chuỗi không mong muốn, như "FORMTEXT", "HYPERLINK \l "_Toc##########" "('#' là ký tự số)," PAGEREF _Toc########## \h 4", vv

các mã sau 'sửa chữa' các vấn đề đơn dòng, nhưng vẫn duy trì tất cả các ký tự không hợp lệ và văn bản không mong muốn:

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

Tôi không biết mình có sử dụng phương pháp sai để trích xuất văn bản hay không, nhưng đó là những gì tôi đã nghĩ ra khi xem POI's quick-guide. Nếu tôi là, cách tiếp cận chính xác là gì?

Nếu đầu ra đó là chính xác, có cách nào tiêu chuẩn để loại bỏ văn bản không mong muốn hoặc tôi có phải tự viết bộ lọc không?

Trả lời

6

Có hai tùy chọn, một tùy chọn được cung cấp trực tiếp trong Apache POI, một tùy chọn khác thông qua Apache Tika (sử dụng Apache POI trong nội bộ).

Tùy chọn đầu tiên là sử dụng WordExtractor, nhưng bọc nó trong một cuộc gọi đến stripFields(String) khi gọi nó. Điều đó sẽ loại bỏ các trường dựa trên văn bản có trong văn bản, những thứ như HYPERLINK mà bạn đã thấy. Mã của bạn sẽ trở thành:

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

Tùy chọn khác là sử dụng Apache Tika. Tika cung cấp trích xuất văn bản và siêu dữ liệu cho nhiều tệp khác nhau, vì vậy cùng một mã sẽ hoạt động với .doc, .docx, .pdf và nhiều tệp khác. Để có được sạch sẽ, văn bản đơn giản của tài liệu văn bản của bạn (bạn cũng có thể nhận XHTML nếu bạn thà), bạn muốn làm điều gì đó như:

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

Giải pháp thứ hai đã không làm việc trong các bài kiểm tra của tôi. TIKA-1.2 trả lại FORMCHECKBOX và các thứ khác từ các tệp .doc. Các tệp .docx hoạt động tốt. – Simon

+0

Tôi khuyên bạn nên dùng thử phiên bản Tika mới nhất, 1.3. Nếu vấn đề vẫn còn xảy ra ở đó, xin vui lòng [nâng cao một lỗi] (https://issues.apache.org/jira/browse/TIKA) và tải lên một tệp mẫu hiển thị nó, vì vậy chúng tôi có thể điều tra! – Gagravarr

+0

Điều này vẫn xảy ra với Tika 1.3 đối với tôi, vì nó đáng giá. – damd

7

Lớp này có thể đọc cả .doc và .docx file trong Java . Đối với điều này tôi đang sử dụng 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(); 
     } 
    } 
} 

Để biên dịch:

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

Để chạy:

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

Hãy thử điều này, làm việc cho tôi và hoàn toàn là một giải pháp POI. Bạn sẽ phải tìm kiếm đối tác HWPFDocument mặc dù. Đảm bảo tài liệu bạn đang đọc có trước từ 97, nếu không thì hãy sử dụng XWPFDocument như tôi.

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 

Bây giờ nếu bạn muốn một phần nào đó bạn có thể sử dụng getparagraphtext nhưng không sử dụng vắt văn bản, sử dụng nó trực tiếp trên đoạn như thế này

for (XWPFParagraph p : adoc.getParagraphs()) 
{ 
    System.out.println(p.getParagraphText()); 
} 
Các vấn đề liên quan