2005年06月30日

很多人用java进行文档操作时经常会遇到一个问题,就是如何获得word,excel,pdf等文档的内容?我研究了一下,在这里总结一下抽取word,pdf的几种方法。
1 .用jacob
其实jacob是一个bridage,连接java和com或者win32函数的一个中间件,jacob并不能直接抽取word,excel等文件,需要自己写dll哦,不过已经有为你写好的了,就是jacob的作者一并提供了。

jacob jar与dll文件下载: http://www.matrix.org.cn/down_view.asp?id=13

下载了jacob并放到指定的路径之后(dll放到path,jar文件放到classpath),就可以写你自己的抽取程序了,下面是一个简单的例子:

import java.io.File;
import com.jacob.com.*;
import com.jacob.activeX.*;
/**
* Title: pdf extraction
* Description: email:chris@matrix.org.cn
* Copyright: Matrix Copyright 2003
* Company: Matrix.org.cn
* @author chris
* @version 1.0,who use this example pls remain the declare
*/
public class FileExtracter{
public static void main(String[] args) {
ActiveXComponent component = new ActiveXComponent("Word.Application");
String inFile = "c:\\test.doc";
String tpFile = "c:\\temp.htm";
String otFile = "c:\\temp.xml";
boolean flag = false;
try {
component.setProperty("Visible", new Variant(false));
Object wordacc = component.getProperty("document.").toDispatch();
Object wordfile = Dispatch.invoke(wordacc,"Open", Dispatch.Method,
new Object[]{inFile,new Variant(false), new Variant(true)},
new int[1] ).toDispatch();
Dispatch.invoke(wordfile,"SaveAs", Dispatch.Method, new Object[]{tpFile,new Variant}, new int[1]);
Variant f = new Variant(false);
Dispatch.call(wordfile, "Close", f);
flag = true;
} catch (Exception e) {
e.printStackTrace();
} finally {
component.invoke("Quit", new Variant[] {});
}
}
}



2. 用apache的poi来抽取word,excel。
poi是apache的一个项目,不过就算用poi你可能都觉得很烦,不过不要紧,这里提供了更加简单的一个接口给你:

下载经过封装后的poi包: http://www.matrix.org.cn/down_view.asp?id=14

下载之后,放到你的classpath就可以了,下面是如何使用它的一个例子:

import java.io.*;
import org.textmining.text.extraction.WordExtractor;
/**
*

Title: word extraction


*

Description: email:chris@matrix.org.cn


*

Copyright: Matrix Copyright 2003


*

Company: Matrix.org.cn


* @author chris
* @version 1.0,who use this example pls remain the declare
*/

public class PdfExtractor {
public PdfExtractor() {
}
public static void main(String args[]) throws Exception
{
FileInputStream in = new FileInputStream ("c:\\a.doc");
WordExtractor extractor = new WordExtractor();
String str = extractor.extractText(in);
System.out.println("the result length is"+str.length());
System.out.println("the result is"+str);
}
}



3. pdfbox-用来抽取pdf文件
但是pdfbox对中文支持还不好,先下载pdfbox: http://www.matrix.org.cn/down_view.asp?id=12

下面是一个如何使用pdfbox抽取pdf文件的例子:

import org.pdfbox.pdmodel.PDdocument.
import org.pdfbox.pdfparser.PDFParser;
import java.io.*;
import org.pdfbox.util.PDFTextStripper;
import java.util.Date;
/**
*

Title: pdf extraction


*

Description: email:chris@matrix.org.cn


*

Copyright: Matrix Copyright 2003


*

Company: Matrix.org.cn


* @author chris
* @version 1.0,who use this example pls remain the declare
*/

public class PdfExtracter{

public PdfExtracter(){
}
public String GetTextFromPdf(String filename) throws Exception
{
String temp=null;
PDdocument.nbsppdfdocument.null;
FileInputStream is=new FileInputStream(filename);
PDFParser parser = new PDFParser( is );
parser.parse();
pdfdocument.nbsp= parser.getPDdocument.);
ByteArrayOutputStream out = new ByteArrayOutputStream();
OutputStreamWriter writer = new OutputStreamWriter( out );
PDFTextStripper stripper = new PDFTextStripper();
stripper.writeText(pdfdocument.getdocument.), writer );
writer.close();
byte[] contents = out.toByteArray();

String ts=new String(contents);
System.out.println("the string length is"+contents.length+"\n");
return ts;
}
public static void main(String args[])
{
PdfExtracter pf=new PdfExtracter();
PDdocument.nbsppdfdocument.nbsp= null;

try{
String ts=pf.GetTextFromPdf("c:\\a.pdf");
System.out.println(ts);
}
catch(Exception e)
{
e.printStackTrace();
}
}

}



4. 抽取支持中文的pdf文件-xpdf
xpdf是一个开源项目,我们可以调用他的本地方法来实现抽取中文pdf文件。

下载xpdf函数包: http://www.matrix.org.cn/down_view.asp?id=15

同时需要下载支持中文的补丁包: http://www.matrix.org.cn/down_view.asp?id=16

按照readme放好中文的patch,就可以开始写调用本地方法的java程序了

下面是一个如何调用的例子:

import java.io.*;
/**
*

Title: pdf extraction


*

Description: email:chris@matrix.org.cn


*

Copyright: Matrix Copyright 2003


*

Company: Matrix.org.cn


* @author chris
* @version 1.0,who use this example pls remain the declare
*/

public class PdfWin {
public PdfWin() {
}
public static void main(String args[]) throws Exception
{
String PATH_TO_XPDF="C:\\Program Files\\xpdf\\pdftotext.exe";
String filename="c:\\a.pdf";
String[] cmd = new String[] { PATH_TO_XPDF, "-enc", "UTF-8", "-q", filename, "-"};
Process p = Runtime.getRuntime().exec(cmd);
BufferedInputStream bis = new BufferedInputStream(p.getInputStream());
InputStreamReader reader = new InputStreamReader(bis, "UTF-8");
StringWriter out = new StringWriter();
char [] buf = new char[10000];
int len;
while((len = reader.read(buf))>= 0) {
//out.write(buf, 0, len);
System.out.println("the length is"+len);
}
reader.close();
String ts=new String(buf);
System.out.println("the str is"+ts);
}
}



关于作者
作者简介:chris,毕业于中国人民大学信息学院。现于香港进行金融分析软件研发,作者亦活跃于 jxta p2p开源软件的开发社区,并热衷于网络安全,AI搜索引擎技术与基于java的游戏引擎技术。
如果大家谁有更好的办法,请告诉作者 : chris@matrix.org.cn

 
1、  下载JACOB包:http://danadler.com/jacob/

2、  安装配置

解压jacobBin_17.zip

(1)jacob.dll所在目录放到PATH中

(2)jacob.jar放到CLASSPATH中

3、使用jacob进行Excel控制,下面是我写的一个测试程序代码

 

import com.jacob.com.*;
import com.jacob.activeX.*;

class ExcelTest
{
  private static ActiveXComponent xl;
  private static Object workbooks = null;
  private static Object workbook = null;
  private static Object sheet = null;
  private static String filename =null;
  private static boolean readonly = false;
 
  public static void main(String[] args)
  {
     String file = "f:\\java\\test.xls";
     OpenExcel(file,false);//false为不显示打开Excel
     SetValue("A1","Value","2");
     System.out.println(GetValue("A3"));
     CloseExcel(false);
  }
 
  //打开Excel文档
  private static void OpenExcel(String file,boolean f)
  {
    try
    {
        filename = file;
        xl = new ActiveXComponent("Excel.Application");
        xl.setProperty("Visible", new Variant(f));
        workbooks = xl.getProperty("Workbooks").toDispatch();
         workbook = Dispatch.invoke(workbooks,
                "Open",
                Dispatch.Method,
                                    new Object[]{filename,
                                    new Variant(false),
                                    new Variant(readonly)},//是否以只读方式打开
                                    new int[1] ).toDispatch();
    }catch(Exception e)
    {e.printStackTrace();}
  }
 
  //关闭Excel文档
  private static void CloseExcel(boolean f)
  {
   try
   {  
     Dispatch.call(workbook,"Save");
         Dispatch.call(workbook, "Close", new Variant(f));
      } catch (Exception e) {
         e.printStackTrace();
     } finally {
     xl.invoke("Quit", new Variant[] {});
      }
  }
 
  //写入值
  private static void SetValue(String position,String type,String value)
  {
     sheet = Dispatch.get(workbook,"ActiveSheet").toDispatch();
     Object cell = Dispatch.invoke(sheet, "Range",
             Dispatch.Get,
                                    new Object[] {position},
                                    new int[1]).toDispatch();
      Dispatch.put(cell, type, value);
  }

  //读取值 
  private static String GetValue(String position)
  {
    Object cell = Dispatch.invoke(sheet,"Range",Dispatch.Get,new Object[] {position},new int[1]).toDispatch();
  String value = Dispatch.get(cell,"Value").toString();
 
  return value;
  }
}

 
 
 
 

  jcob的原理是通过一个接口来操作word的activex对象。现在的版本是1.9。
首先:把jcob.dll拷贝到system32目录下。
其次:把jcob.jar的路径放置在classpath目录下。
最后:编写访问类。


  public static void main(String[] args) {
    //启动word,生成一个ActivexComponent对象
    ActiveXComponent app = new ActiveXComponent("Word.Application");
    //要转换的word文件
    String inFile = "D:\\project\\java_word\\java_word\\wordtemplet.doc";
    //要报存的目标文件
    String tpFile ="D:\\project\\java_word\\java_word\\wordtemplet3.doc";
    boolean flag = false;
    Dispatch xlo = app.getObject();
    String oldText="1234";
    String newText="test";
    boolean visible=false;
    String bookMarkKey="LB_KJGG";
    try {
      //设置word不可见
      app.setProperty("Visible", new Variant(visible));
      //log.info("设置word不可见成功!");
      System.out.println("设置word不可见成功!");
      Dispatch docs = app.getProperty("Documents").toDispatch();
      Dispatch doc = Dispatch.invoke(docs, "Open", Dispatch.Method
                                   ,new Object[]
                                   {inFile, new Variant(false), new Variant(true)}
                                   , new int[1]).toDispatch(); //打开word文件
      //在word2003的vba文档中application有UserName属性。
      String userName=app.getPropertyAsString("UserName");
      System.out.println("用户名:"+userName);
      Dispatch selection=app.getProperty("Selection").toDispatch();
      //得到一个组件
      System.out.println("Selection");
      Dispatch find = app.call(selection, "Find").toDispatch();

       //查找什么文本
       Dispatch.put(find, "Text", oldText);
       //替换文本
       Dispatch.call(find,"ClearFormatting");
       Dispatch.put(find, "Text", oldText);
       Dispatch.call(find, "Execute");
       Dispatch.put(selection, "Text", newText);
       // Dispatch.call(app, "SaveAs", inFile);
       System.out.println("replace");
      
       //把指定的值设置到指定的标签中去
       Dispatch activeDocument=app.getProperty("ActiveDocument").toDispatch();
       System.out.println("activedocument");
       Dispatch bookMarks = app.call(activeDocument, "Bookmarks").toDispatch();
       System.out.println("bookmarks");
       boolean bookMarkExist1=Dispatch.call(bookMarks,"Exists",bookMarkKey).toBoolean();
       if(bookMarkExist1==true){
         System.out.println("exists bookmark!");
         Dispatch rangeItem = Dispatch.call(bookMarks, "Item",bookMarkKey).
                        toDispatch();
                    System.out.println("range item!");
                    Dispatch range = Dispatch.call(rangeItem, "Range").toDispatch();
                    System.out.println("range !");
                    //取标签的值
                    String bookMarkValue=Dispatch.get(range,"Text").toString();
                    bookMarkValue="test";
                    if(bookMarkValue!=null){
                      Dispatch.put(range, "Text",
                             new Variant(bookMarkValue));
                    }
        
       }
       else{
         System.out.println("not exists bookmark!");
       }
      //保存文件
      Dispatch.invoke(doc, "SaveAs", Dispatch.Method, new Object[] {tpFile, new Variant(0)}                      , new int[1]);
      //作为word格式保存到目标文件
      Variant f = new Variant(false);
      Dispatch.call(doc, "Close", f);
      flag = true;
    }
    catch (Exception e) {
      e.printStackTrace();
    }
    finally {
      app.invoke("Quit", new Variant[] {});
    }


2005年06月29日


我这两天试着用java把word文档转换为htm文档,现已搞定,经验如下:

1.下载jacob_18.zip:打开网址:http://sourceforge.net/projects/jacob-project/,然后点击[View ALL Project Files] ,里面有jacob的1.8版本下载;

2.解压jacob_18.zip,将jacob.jar放在“JAVA_HOME\jre\lib\ext\”目录下(“JAVA_HOME”为你所安装的JDK目录),例如“C:\java\jre\lib\ext\”,将jacob.dll放在目录“C:\jacob\”下;

3.设置path:右击“我的电脑” –> 选择“高级” –> 点击“环境变量” –> 在“系统变量”中双击变量“path”,在后边加上“C:\jacob;”,点击“确定”;

4.编写程序(文件名为WordToHtm.java):
/**
 * File Name : WordToHtm
 * Author :
 * Date : 2005.4.26
 * Note : convert word file to htm file.
 */

import java.io.File;
import com.jacob.com.*;
import com.jacob.activeX.*;

public class WordToHtm
{
 public static void main( String[] args )
 {
  //启动word
  ActiveXComponent app = new ActiveXComponent( "Word.Application" );
 
  //要转换的word文件
  String inFile = "D:\\test\\my.doc";
 
  //目标文件
  String tpFile = "D:\\test\\my.htm";
 
  boolean flag = false;
 
  try
  {
   //设置word不可见
   app.setProperty( "Visible", new Variant(false) );
  
   Object docs = app.getProperty( "Documents" ).toDispatch();
  
   //打开word文件
   Object doc = Dispatch.invoke(
    docs ,
    "Open" ,
    Dispatch.Method ,
    new Object[]
    {
     inFile ,
     new Variant(false) ,
     new Variant(true)
    } ,
    new int[1]
          ).toDispatch();
  
   //作为html格式保存到临时文件
   Dispatch.invoke(
    doc ,
    "SaveAs" ,
    Dispatch.Method ,
    new Object[]
    {
     tpFile,new Variant( 8 )
    } ,
    new int[1]
         );
  
   Variant f = new Variant( false );
   Dispatch.call( doc , "Close" , f );
   flag = true;
  }
  catch( Exception e )
  {
   e.printStackTrace();
  }
  finally
  {
   app.invoke( "Quit" , new Variant[]{} );
  }
 }
}

5.将word文件my.doc放置在“D:\test\”目录下;

6.编译WordToHtm.java并运行后,你就会发现在“D:\test\”目录下出现了my.htm文件。

附注:

1.我使用的操作系统是windowXP,其它的系统我没有试过;

2.我使用的word的版本是microsoft @ word 2002,如果是更新的版本有可能会不成功(这我也没试过);

3.我所使用的jacob的版本是1.8,如果使用1.7或1.6版本则会出错,使用1.9版本也不行,编译不会成功,也许是因为1.9还处于开发阶段,尚不完善。


前一段时间为这个问题头疼的不得了,后来查阅了资料终于解决了;现将程序放出,以便以后参考。


//——————————————————————————
//版权所有 (C) 浪潮集团商用系统有限公司  保留所有权利
//文件名称: wordtohtml           文件版本: 1.00.00
//作    者: 郭铸     作者邮箱: guozhu@langchao.com  完成日期: 2004-10-20
//文件描述:
//其它描述:
//类 列 表:
//  wordtohtml: 将指定目录下面所有的doc文件转化为HTML并存储在相同目录下
//修改历史:
//  #   版本     修改日期    作者                 修改内容
//  —————————————————————————-
//  1   1.00.01  2004-10-14  作者姓名             修改内容描述
//  —————————————————————————-
//——————————————————————————
import com.jacob.com.*;
import com.jacob.activeX.*;
import java.io.*;

//取得指定目录下面所有的doc文件名称
public class wordtohtml
{
//——————————————————————————
//方法原型: change(String paths)
//功能描述: 将指定目录下面所有的doc文件转化为HTML并存储在相同目录下
//输入参数: String
//输出参数: 无
//返 回 值: 无
//其它说明: 递归
//——————————————————————————
 public static void change(String paths, String savepaths)
 {
  
  File d = new File(paths);
  //取得当前文件夹下所有文件和目录的列表
  File lists[] = d.listFiles();
  String pathss = new String("");

  //对当前目录下面所有文件进行检索
  for(int i = 0; i < lists.length; i ++)
  {
   if(lists[i].isFile())
   {
    String filename = lists[i].getName();
    String filetype = new String("");
    //取得文件类型
    filetype = filename.substring((filename.length() – 3), filename.length());
   
    //判断是否为doc文件
    if(filetype.equals("doc"))
    {
     System.out.println("当前正在转换……");
     //打印当前目录路径
     System.out.println(paths);
     //打印doc文件名
     System.out.println(filename.substring(0, (filename.length() – 4)));
    
     ActiveXComponent app = new ActiveXComponent("Word.Application");//启动word
    
     String docpath = paths + filename;
     String htmlpath = savepaths + filename.substring(0, (filename.length() – 4));
    
     String inFile = docpath;
    //要转换的word文件
     String tpFile = htmlpath;
    //HTML文件

     boolean flag = false;
    
     try
     {
      app.setProperty("Visible", new Variant(false));
        //设置word不可见
      Object docs = app.getProperty("Documents").toDispatch();
      Object doc = Dispatch.invoke(docs,"Open", Dispatch.Method, new Object[]{inFile,new Variant(false), new Variant(true)}, new int[1]).toDispatch();
        //打开word文件
      Dispatch.invoke(doc,"SaveAs", Dispatch.Method, new Object[]{tpFile,new Variant(8)}, new int[1]);
        //作为html格式保存到临时文件
      Variant f = new Variant(false);
      Dispatch.call(doc, "Close", f);
      flag = true;
     }
     catch (Exception e)
     {
      e.printStackTrace();
     }
     finally
     {
      app.invoke("Quit", new Variant[] {});
     }
     System.out.println("转化完毕!");
    }
   }
   else
   {
    pathss = paths;
    //进入下一级目录
    pathss = pathss + lists[i].getName() + "\\";   
    //递归遍历所有目录
    change(pathss, savepaths);
   }
  }
 
 }
//——————————————————————————
//方法原型: main(String[] args)
//功能描述: main文件
//输入参数: 无
//输出参数: 无
//返 回 值: 无
//其它说明: 无
//—————————————————————————— 
 public static void main(String[] args)
 {
 
  String paths = new String("D:\\Work\\2004.10.8\\test system\\test01\\word\\");
  String savepaths = new String ("D:\\Work\\2004.10.8\\test system\\test01\\html\\");

  change(paths, savepaths);

 }
}

其中import的jar包是一个开源的东东,网上搜索即得。
Dispatch.invoke(doc,"SaveAs", Dispatch.Method, new Object[]{tpFile,new Variant(8)}, new int[1]);
修改Variant(8)},里面得参数即可将Word转化为各种类型。