[Java] 使用jawin操作Word文檔的Java程式



/
 
CreateWordDoc.java
 
 
1.Create a new word document;

 * 2.assign font name

 * 3.assign font size

 * 4.write two sentences

 * 5.save it

 * 6.close it

  7.exit word.
 

  @version     vision: 1.0
 
@author      howwa@sina.com

import org.jawin.DispatchPtr;
import org.jawin.win32.Ole32;


public class CreateWordDoc {

public static void main(String[] args) {
  try {
    Ole32.CoInitialize();
    //初始化
    DispatchPtr app = new DispatchPtr(“Word.Application”);
    //创建word对象
    app.put(“Visible”, true);
    //使word 可见
    DispatchPtr docs = (DispatchPtr)app.get(“Documents”);
    //取得document对象集合(Documents)
    DispatchPtr doc = (DispatchPtr) docs.invoke(“Add”); 
    //新增一个文档
    app.invoke(“Activate”);
    //激活当前文档
    DispatchPtr objTextFont = (DispatchPtr)((DispatchPtr) doc.get(“Content”)).get(“Font”);
    //取得Font对象
    objTextFont.put(“Name”,”黑体”);
    //设置字体
    objTextFont.put(“Size”,”48”);
    //设置字号
    DispatchPtr docSelection = (DispatchPtr)app.get(“Selection”);
    //取得Selection对象
    docSelection.invoke(“TypeText”,”Jawwin test text!nJawin测试文本。”);
    //使用TypeText方法添加文本
    doc.invoke(“SaveAs”,”c:\jawintest.doc”); 
    //保存文档(保存在C盘根目录下)
    //doc.invoke(“Close”);
    //关闭当前文档,去掉前面的注释符并重新编译后可生效
    //app.invoke(“Quit”);
    //退出Word,去掉前面的注释符并重新编译后可生效

    Ole32.CoUninitialize();  //释放对象
} catch (Exception e) {
e.printStackTrace();
}
}

}

[Java] 關於Java調用dll的方法

Java语言本身具有跨平台性,如果通過Java調用DLL的技术方便易用,使用Java開發前台界面可以更快速,也能帶来跨平台性。

    Java調用C/C++寫好的DLL庫時,由於基本數據類型不同、使用字節序列可能有差異,所以在參數傳遞過程中容易出現問題。

    使用Java調用DLL動態鏈接庫的方案通常有三種︰JNI, Jawin, Jacob.




 其中JNI(Java Native Interface)Java語言本身提供的調用本地已編譯的函數庫的方法,本身具有跨平台性,可以在不同的機器上調用不同的本地庫。JawinJacob都是sourceforge.net的开源项目,都是基于JNI技术的依赖Windows的实现,使得在Windows平台下使用COMDLL的更加方便。

一、JNI



JNI的應用方案是基於Java類和本地函數相映射的。其使用DLL的步驟還是相對比較麻煩,不但涉及到Java編程,還涉及到C/C++編程。

JNI的使用步驟是︰

1.編寫Java類,用該類將DLL對外提供的函數服務進行聲明,其中的Java方法均聲明為native,其方法簽名可以自定義,不用實現函數體。

2.Javah工具將該Java類生成對應的.h頭文件。

3.最重要的比較麻煩的一步︰編寫C/C++代碼實現.h頭文件中聲明的函數,該C/C++代碼中包含jni.h頭文件,並且編寫代碼時使用其中定義好的 數據類型作為函數的輸入和返回數據類型進行編程。用這種方法實現數據類型轉換。例如數據類型︰boolean(java)    jboolean(jni.h: typedef unsigned char jboolean),在自己編寫的C/C++代碼中使用數據類型jboolean映射Java中的boolean類型。在該步驟中,可以在C/C++代碼 中調用已經存在的DLL庫。

4.另外編寫的Java代碼時就可以使用該Java類了。

在第3步中,編寫C/C++函數時,可以使用一個叫interface pointerenv指針來調用JNI提供的一系列(很多)函數,用這些函數來訪問JVM的對象和數據。

使用JNI的缺點︰使用比較麻煩,需要對已有的DLL進行封裝,需要對C/C++比較了解。

使用JNI的優點︰可以跨平台調用本地庫。


二、Jawin 
官方網站︰http://jawinproject.sourceforge.net/;/1218204518239/)


官方文檔(Jawin使用DLL)http://jawinproject.sourceforge.net;/1218204524829/)/jawinuserguide_dll.html


Jawin的應用方案是基於函數調用時采用原始字節流傳遞數據的。就是在Java中指明一個DLL中的某個函數後,透過原始位元組流(需要考慮參數數據類型所占的存儲位元組數及系統使用的位元組序列)傳遞給該DLL函數需要的參數,其返回值也是透過原始位元組流解析的模式獲得正確的值。

Jawin的使用步驟︰

1.環境配置︰下载JawinJawin.dll放入工程目錄下;Jawin.jar相關jar文件加入到運行庫中(LibPath或者Eclipse下配置工程的BuildPath-AddLibrary)

2.獲得函數指針︰new FuncPtr(“DllFileName.DLL”, “dllFunctionName”);

3.LittleEndianOutputStream將函數需要的參數寫入到一個原始字節流NakedByteStream

4.最重要的一步︰調用FuncPtr.invoke()。傳入參數比較複雜。

5.解析上一步的返回值(字節數組)

4步中傳入的參數包括︰

1.指令字符串。一個”XXX:Y:ZZZ”格式的字元串。其含義分別是傳入參數中的每個位元組的數據類型意義、返回值的類型、需要從傳入指標中讀取的數據(inout類型參數)。比如︰

函數簽名int func(int, int, struct s, char); //其中struct s調用完函數後需要讀出,struct s所占字節數為16

其指令字符串為︰IIP16G:I:L4L4n16L4。該字元串在解析返回值(位元組數組)時,首先應該是返回類型I對應的4個位元組,然後是inout類型的參數中n16對應的16個位元組。

其中字符串的意義可以在Jawin提供的文件instructions.h中找到,或者在官方文檔(Jawin數據指令)中找到常用的一些指令字符串的意義。

2.傳入參數的總字節大小。

3.前面寫好的傳入參數的原始字節流。

4.一個object數組。

5.ReturnFlags,用以根據C/C++返回值將C/C++的錯誤轉換為Java的異常並拋出。其中CHECK_NONE表示不檢 查;CHECK_FALSECHECK_WIN32分別表示返回0FALSESUCCESS,根據是否出錯決定是否拋出異 常;CHECK_HRESULT表示使用COM模型中的HRESULT作為返回值,其錯誤碼可以配置。

使用Jawin的缺點︰不方便調試,幾乎所有的錯誤都拋出同樣的異常COMException;需要對數據類型的轉換比較了解;不能跨平台,對Windows的依賴性比較強。

使用Jawin的優點︰方便使用,不用進行C/C++開發,不用對原始DLL進行封裝就可以方便使用。


三、Jacob

官方文檔︰http://danadler.com/jacob/;/1218204537653*/)

JacobJava-Com Bridge的縮寫,也可以用來調用DLL。其底層也是使用JNI實現,也具有Windows的平台倚賴性,由於網上有人反映其易用性不如jawin,所以沒有深入了解。


[Java] 利用jawin完成調用window中dll的調用[轉載]

由於項目的特殊需求,我們必須在程式調用window的dll。
開始我們用jni,後來由於調用的dll太多,而且很煩瑣。所以,我們決定用開源的jawin調用。
jawin 可以對dll中的方法進行調用,也可以調用com中的方法.內部還提供了一個工具,直接對 com組件匯出成 java的類,個人認為很方便。


有三篇…待整理

========================================================

========================================================
下面是我們作的一個測試,很順利便通過了。
1、下載jawin︰http://jawinproject.sourceforge.net/;/1218107116443/)。
2、配置︰
    》將jawin.jar放於%JAVA_HOME%jrelibext下 。
    》將jawin.dll放於c:winntsystem32下。否則將出現錯誤︰COMException : no jawin in java.library.path;
    也可將jawin.dll放於每個項目目錄下。

   》至此在Editplus中調試Jawin/NJawin的例子,可以透過。 而在Eclipse中有時還會出上面的錯誤︰COMException : no jawin in java.library.path。
   》在Eclipse中,選單->window->preference->Java->installed JREs 將原來的remove,重新建一個指到你的java sdk目錄。
   》 ok了。
 3、程式測試︰

     》調用 dll,dll 的模式不需要匯出了,直接調用就可以了,下面是下載的包中提供的一個例子:
     》我在win2000下,測試透過。
/
 
Created on Dec 22, 2005
 
 
/
import org.jawin.FuncPtr;

import org.jawin.ReturnFlags;

/*
 
@author gf  mail to gf@163.com
 
 
TODO To change the template for this generated type comment go to
  Window - Preferences - Java - Code Style - Code Templates
 
/
public class GfJawinTest {

       public static void main(String[] args) {

              try {

                     FuncPtr msgBox = new FuncPtr(“USER32.DLL”, “MessageBoxW”);

                  

                     msgBox.invoke_I(0, “Hello From a DLL”, “From Jawin”, 0, ReturnFlags.CHECK_NONE);

              } catch (Exception e) {

                     e.printStackTrace();

              }

       }

}
 轉自︰http://www.blogjava.net/gf7/archive/2005/12/22/25041.html

========================================================

========================================================

1.下載NJawin,將jawin.jar放於%JAVA_HOME%jrelibext下

2.將jawin.dll放於c:winntsystem32下。否則將出現錯誤︰COMException : no jawin in java.library.path;

   也可將jawin.dll放於每個項目目錄下。

3.至此在Editplus中調試Jawin/NJawin的例子,可以通過。

  而在Eclipse中有時還會出上面的錯誤︰COMException : no jawin in java.library.path。

4.在Eclipse中,選單->window->preference->Java->installed JREs

  將原來的remove,重新建一個指到你的java sdk目錄。
5. ok了。

jawin下載: Jawin;/1218107102504/)
hinet: jawin.zip

========================================================

========================================================


今天老师和我聊起Java调用Win API的事,回来查了下,SUN官方提供的JNI调用时还要自己生成头文件,对已有的DLL再次进行封装。需要对C++非常熟悉,因为要写C++代码。不过还好还有另一种解决方案——Jawin。

官方网站:http://jawinproject.sourceforge.net

把lib文件夹下的jawin.jar和jawin-stubs.jar放到%JAVA_HOME%jrelibext 目录下
把bin文件夹下的
jawin.dll放到%SystemRoot%System32 目录下

然后就可以运行demo下的Hellodll.java了:

/ HelloDll.java -
This file is part of the Jawin Project: http://jawinproject.sourceforge.net/
Please consult the LICENSE file in the project root directory,
or at the project site before using this software. /


/ $Id: HelloDll.java,v 1.3 2004/06/14 20:16:38 arosii_moa Exp $ /

package demos;

import org.jawin.COMException;
import org.jawin.FuncPtr;
import org.jawin.ReturnFlags;


/* Demo that uses the Win32 MessageBoxW API-method.
@version     $Revision: 1.0 $
@author      虫的传人, http://hi.baidu.com/虫的传人/
/
public class HelloDll {


public static void main(String[] args) throws Exception {
   FuncPtr msgBox = null;
   try {
    msgBox = new FuncPtr(“USER32.DLL”, “MessageBoxW”);
    msgBox.invoke_I(0, “Hello From a DLL”, “From Jawin”, 0, ReturnFlags.CHECK_FALSE);
   } catch (COMException e) {
    // handle exception
    e.printStackTrace();
    throw e;
   } finally {
    if (msgBox != null) {
     try {
      msgBox.close();
     } catch (COMException e) {
      // handle fatal exception
      e.printStackTrace();
      throw e;
     }
    }
   }
}
}


调用自己写的dll:

import org.jawin.COMException;
import org.jawin.FuncPtr;
import org.jawin.ReturnFlags;


public class nativeDll {
public static void main(String[] args) throws Exception {
   int result1,result2;
   FuncPtr test1 = null;
   FuncPtr test2 = null;
   try {
    test1 = new FuncPtr(“demo.dll”, “test1”);
    test2 = new FuncPtr(“demo.dll”, “test2”);
    result1 = test1.invoke_I(5, 6, ReturnFlags.CHECK_NONE);
    result2 = test2.invoke_I(5, 6, ReturnFlags.CHECK_NONE);
    System.out.println(“5 plus 6 is “ + result1);
    System.out.println(“5 multiply 6 is “ + result2);
   } catch (COMException e) {
    e.printStackTrace();
   } finally {
    if (test1 != null) {
     try {
      test1.close();
     } catch (COMException e) {
      e.printStackTrace();
     }
    }
    if (test2 != null) {
     try {
      test2.close();
     } catch (COMException e) {
      e.printStackTrace();
     }
    }
   }
}
}


命令行运行:javac nativeDll.java
java -classpath “.;%JAVA_HOME%jrelibextjawin.jar” nativeDll

注意,这里一定要加-classpath “.;%JAVA_HOME%jrelibextjawin.jar” 不然会提示

Exception in thread “main” java.lang.NoClassDefFoundError: org/jawin/COMExceptio
n
Caused by: java.lang.ClassNotFoundException: org.jawin.COMException
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClassInternal(Unknown Source)


特别注意”.;”,不加的话会提示

Exception in thread “main” java.lang.NoClassDefFoundError: nativeDll
Caused by: java.lang.ClassNotFoundException: nativeDll
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClassInternal(Unknown Source)