網上收集的一些Java應用
我先說說在JBUILDER中將程序外觀變的更酷的辦法! JAVA程序默認的外觀(LOOKANDFEEL)可以改變為JAVA外觀、MOTIF外觀、 WINDOWS 外觀、MAC外觀; 而JAVA外觀又有五種風格分別是海藍寶石風格、祖母綠風格、紅寶石風格、木炭風格、 高對比風格。 外觀改變具體
我先說說在JBUILDER中將程序外觀變的更酷的辦法!
JAVA程序默認的外觀(LOOKANDFEEL)可以改變為JAVA外觀、MOTIF外觀、
WINDOWS外觀、MAC外觀;
而JAVA外觀又有五種風格分別是海藍寶石風格、祖母綠風格、紅寶石風格、木炭風格、
高對比風格。
外觀改變具體方法如下:
1:可以直接在程序中調用下面三個中的一個:
import
javax.swing.*;
UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel") ;
UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel") ;
UIManager.setLookAndFeel("com.sun.java.swing.plaf.
windows.WindowsLookAndFeel") ;
2:或采用菜單來變換:
import javax.swing.*;
JMenuBar mb = new JMenuBar();
JMenu file = new JMenu("Look & Feel", true);
ButtonGroup buttonGroup = new ButtonGroup();
final UIManager.LookAndFeelInfo[] info = UIManager.getInstalledLookAndFeels();
for (int i = 0; i < info.length; i++) {
JRadioButtonMenuItem item = new
JRadioButtonMenuItem(info[i].getName(), i == 0);
final String className = info[i].getClassName();
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
try { UIManager.setLookAndFeel(className); }
catch (Exception e) { System.out.println(e); }
SwingUtilities.updateComponentTreeUI(TouchyFeely.this); }
});
buttonGroup.add(item);
file.add(item);
}
mb.add(file);
setJMenuBar(mb);
}
以前發表過內容的大富翁朋友請將內容改為JBUILDER相關內容。謝謝。
希望多多寫入精華,不要灌水!
來自:humanc2d4, 時間:2003-5-16 14:45:00, ID:1867298
我再說一下JBUILDER中APPLET的數字簽名(轉載自:編程愛好者)
自從Java技術開始應用以來,人們對Java平臺的
安全性以及由于部署Java技術所引發的安全問題給予了極大的關注。特別是在1998年11月Java2發布后,Java的安全體系結構發生了根本的改進,對于終端用戶而言,它可以保護文件和私人數據不被惡意的程序或病毒感染和破壞,鑒別代碼提供者的身份。對于
開發者而言,通過使用API方法,能夠將安全性功能集成到應用程序中,因為API的體系結構能夠定義和集成對特定的資源的使用權限、加密、安全性管理、策略管理,并提供了一些類來管理公鑰/密鑰對及信任用戶群的公鑰證書。同時系統管理員、開發者和用戶可以使用它提供的工具管理鑰匙庫,在JAR文件中生成數字簽名、簽名的完整性檢測、創建和修改策略文件。按照Java設計者的觀點,Java安全包括2個方面的內容,首先將Java作為一種安全的平臺提供給用戶,在此平臺上,可安全地運行Java程序;其次提供用Java編程語言實現的安全工具和服務,它使得諸如企業界這樣一些對安全非常敏感的領域也可應用Java技術。本文將就這二個方面介紹Java2的安全性新特性以及該新特性下的Applet數字簽名的具體實現方法?!?
Java2采用了如圖1所示的新的安全體系結構,并基于這種安全體系結構提供了很多新特?
1.1 密紋訪問控制
這種能力從一開始就在JDK中存在。但要使用它,應用程序的編寫者不得不做大量的編程工作?例如,創建SecurityManager和Classloader類的子類并使其用戶化。HotJava1.0就是一個這樣的應用程序,它允許瀏覽器用戶在幾個不同的安全等級上進行選擇。然而,這種編程涉及非常敏感的安全問題,它要求
程序員對計算機安全有精深的理解和純熟的技巧。新的安全體系結構將使這些變得簡單而安全。
1.2 易于配置的安全策略
與上述情況相似,這種能力在原來的JDK中也是存在的,但是不便于使用,而且編寫安全代碼也不是簡單明了的事情。于是,人們期望能夠允許應用程序的編寫者和用戶能夠不通過編程來設置安全策略。
1.3 便于擴展的訪問控制結構
一直到JDK1.1為止,為了創建1個新的訪問許可,你必須在SecurityManager類中增加1個新的check方法。新的安全體系結構則允許設置各類訪問許可(每個都表示對1個系統資源的訪問),并能對所有正確訪問許可(包括未定義的許可)進行自動處理。
1.4 安全檢查擴展至所有Java程序
那種所有本地代碼是可信的內置概念將不復存在,取而代之的將是本地代碼(例如非系統代碼,安裝在本地的應用程序包等)服從于與Applet相同的安全控制,但是可以聲明對本地代碼的政策是最寬容的,從而使這些代碼可被認為是完全可信而有效地運行。上述原則也可應用于已簽字的Applet和任何Java應用程序。
2 Java2安全體系的概念及運行機制
2.1 保護域
Java2安全體系結構中的一個基本的概念是保護域(Protected Domain)。1個域可通過對象集來劃分范圍,這些對象當前可由1個主體直接訪問。而主體是在計算機系統中被授予許可的實體。JDK1.0所利用的沙箱就是一個有著固定邊界的保護域實例。保護域的概念是一種在保護單元間起著分組和隔離作用的便利機制。例如,我們可以將保護域分開以避免它們之間的直接交互作用,于是,任何允許的交互作用必須通過可信系統代碼或被有關的域所明確允許。
保護域通常分為明確的2個類別,系統域和應用程序域。所有被保護的外部資源如:文件系統、
網絡設施以及屏幕和鍵盤等僅能通過系統域來訪問。圖2中顯示了1個Java應用環境的域的組成。從概念上講,1個域包括1組類,這些類的實例被授予相同的一組許可。保護域是由現行策略所確定的。Java應用程序環境保持了來自代碼(類和實例)到它們的保護域然后再到它們的許可的映射,如圖3所示。1個線程的執行可能完全發生在1個單一的保護域中,也可能涉及1個應用程序域或是系統域。例如:1個打印消息的應用程序將不得不與系統域發生交互作用,因為系統域是唯一對輸出流的訪問點。在此種情況下的任何時候,應用程序域都不能通過調用系統域獲得除打印消息外的任何額外許可,否則將是一個嚴重的安全性隱患。在相反的情形下,1個系統域從1個應用程序域中調用1個方法,如當1個AWT系統域調用1個Applet的繪畫方法來顯示這個Applet時,有效訪問權限與應用程序域所允許的當前權限在任何時候都相同,這一點也是同樣至關重要的。換句話說,一個具有較低權限的域不能通過調用一個更高權限的域,或被一個更高權限的域所調用來獲得額外的許可。上述有關1個線程涉及2個保護域的討論自然地歸納為1個遍歷多重保護域的線程,計算許可的一個簡單而謹慎的經驗做法是:
?。?)一個執行線程的許可集可被認為是由該線程所遍歷的所有保護域的許可的交集。
?。?)當1條代碼調用doPrivileged方法時,執行線程的許可集被認為是包括所有代碼的保護域以及由它直接或間接調用的保護域的權限。即通過doPrivileged方法可使1條可信代碼能臨時訪問更多的資源,這在某些情況下是必要的。例如,1個應用程序可能不被允許直接訪問包含字體的文件,但是,顯示文本的系統實用程序必須代表用戶獲得那些字體。
在執行期間,當請求訪問1個關鍵系統資源(如文件I/O和網絡I/O)或者API方法需要執行1個敏感的操作時,例如讀1個文件,資源處理代碼直接或間接地調用1個特殊的稱為訪問控制(A
clearcase/" target="_blank" >ccessController)類的方法,訪問控制類通過檢查調用棧來作出決定是否準予該請求或操作發生。在調用棧中是執行該操作需要調用的一些類的成員方法,因為每個類都屬于一些保護域,每個保護域都建立了一些策略,因此在調用棧的每個方法都被分配了1組權限。訪問控制類由棧頂開始,自頂向下檢查每個方法,看是否方法被所在的保護域所允許,如果發現一個方法權限沒有得到允許,訪問控制
就拋出安全性異常;反之,如果到達棧底仍未拋出異常,即說明調用棧中的所有方法均滿足保護域的權限要求,訪問控制允許操作發生。其中有一種特殊的情況,即當訪問控制遍歷調用棧時,將查找是否存在優先域(Privileged Domain),如果存在優
域,即使沒有到達棧底,訪問控制也將停止遍歷調用棧并允許操作發生。雖然新的安
機制初看上去增加了許多調用API方法的消耗,但是Java2確實使用了一些技術去加速
查權限的過程,例如訪問控制將過濾掉重復的域并在遇到第一個優先域時停止檢查,
說明額外的操作將是一個本地的方法調用,SUN的基準
測試顯示了新的安全檢查是相當快的。
最后,每個域包括系統或應用程序域可以對其域邊界內的內部資源進行附加保。例如,一個
銀行系統的應用程序可能需要支持并保護其內部的一些概念,如查帳、存
和取款等。由于此種保護的語義不像那些可預測的語義可以被JDK預置,因而,在這個
次上的保護最好留給系統或應用程序開發員來做。
目前,1個域單獨地由1個代碼來源(CodeSource)鑒別,它封裝了在該域中運行的代碼的2個特性:代碼基址和公共密鑰證書集,公共密鑰對應于在該域中為所有代碼簽字的私有密鑰。因而,由相同的密鑰簽字和來自相同URL的類被放在同一個域中。1個域還包含在該域中授予代碼的許可,它是由現行安全策略所決定的。
2.2 證書、鑰匙庫及其相關工具
在Java2的安全體系下,1個Applet開發和運行的過程如下:
在代碼的分發端:
?。?)開發Java源程序并對其進行編譯。
?。?)用JAR工具對類文件和資源文件進行封裝。
?。?)用keytool創建公鑰和密鑰,生成X。509V1簽名證書,輸出證書。
?。?)通過jarsigner工具用生成的密鑰對JAR文件進行數字簽名。
在代碼的接收端:
?。?)用keytool輸入證書視其為可信任。
?。?)用policytool創建和修改安全性策略配置文件,授權請求的訪問權限。
?。?)從網絡取得字節碼,用公鑰驗證數字簽名證書和文檔代碼的完整性。
?。?)驗證字節碼的合法性,根據策略文件分配相應權限。
?。?)執行代碼,完成后被垃圾回收器回收內存。
在用公鑰驗證數字簽名證書之前,接收方需要確認公鑰自身的
可靠性,因此通常情況是提供一個包含公鑰的證書而不是公鑰自身。1個證書包括:
?。?)1個公鑰。
?。?)1個唯一的名字實體(個人或公司),它是證書的所有者,包含用戶名字、公司、組織、城市、地址、國家代碼、省份等信息。
?。?)數字簽名:1個證書被1個分發者的實體簽名,保證證書確實包含另1個
實體(所有者)的公鑰。
?。?)分發者的標識名信息。
對于接收者可以用分發者的公鑰來驗證他的數字簽名,檢查證書的合法性。然而公鑰可能包含在另一個證書中,而數字簽名需要用另一個證書的分發者的公鑰來驗證,這樣嵌套下去,直到一個公鑰被接收者確認是可信任的。如果接收者不能建立信任鏈,例如:1個分發者的證書不合法,那么可以用keytool-import命令來計算指紋,每個指紋是一個相關的短數字,它唯一可靠地標識證書(指紋是一個用信息摘要算法計算的證書信息的哈希值),接收者可以呼叫證書的所有者,并比較發出的證書和接收證書的指紋,如果指紋相同,則證書不同。因此能夠保證證書在傳遞的過程中未被修改。另一個潛在的問題是發送者身份的標識,有時一個證書是自簽名的,即使用證書中的公鑰相對應的密鑰進行簽名,如果接收者已經知道或信任發送者,那么就沒有任何問題。否則發送者需要從一個可信任的第3方得到證書,這個第3方通常是一個證書的授權機構CA,那么首先發送一個自簽名的證書簽名請求CSR給CA,由CA驗證CSR的簽名及發送CSR的身份、許可證以及其它信息。然后CA通過一個用CA的密鑰進行簽名的證書,授權CSR的發送者作為公鑰的所有者,任何人只要信任CA的公鑰,都可以用之來驗證證書的簽名,很多情況下CA自身有一個來自更高一級的CA的證書,從而構成證書鏈。所有信任的證書實體都可以作為信任證書被引入鑰匙庫,每個證書中的公鑰都可以用來驗證用相應的密鑰生成的簽名。
發送者在發送簽名的代碼和文檔時還相應提供包含與簽名的密鑰相應的公鑰證書。用keytool-export命令或API函數可以從鑰匙庫中輸出證書到文件中,然后將這個文件發送給需要的接收者,由接收者用keytool-import命令或API函數將其引入鑰匙庫中。如果用jarsigner工具為JAR文件生成簽名,他會從鑰匙庫中取出證書及證書鏈,并和簽名一起放入JAR文件。
密鑰和相應的公鑰證書存放在一個由口令保護的
數據庫中,稱為鑰匙庫(keystore)。1個鑰匙庫包含2種類型的條目,可信任的證書條目,鑰匙和證書條目,每個都包含1個密鑰和與密鑰相應的公鑰證書,在鑰匙庫中的每個條目都有1個別名進行標識。1個鑰匙庫的所有者在鑰匙庫中可以有多個鑰匙,可以通過不同的別名進行訪問,每個別名通常是用鑰匙庫的所有者使用的鑰匙的特定角色來命名,別名也可以標識鑰匙的目的。例如:
SignPersonalEmail可以被用來標識1個鑰匙庫的條目,它的密鑰用于簽名個人郵件,SignJarFiles用于標識1個條目,它的密鑰用于簽名JAR文件。
3 Applet的數字簽名認證實現的具體方法、步驟
3.1 結合我自己開發的基于JAVA2的Applet
我的項目是使用APPLET制作一個實時消息隊列監控程序,由于涉及到了本地資源,對APPLET一定要進行數字簽名和認證。我使用的環境是WINDOWS2000,應用服務器是WEBLOGIC6.0,開發環境是JBUILDER4.0。之前我提醒大家一定要注意服務器端和客戶端的概念。那些文件應該在服務器端,那些文件應該在客戶端。
首先在客戶端使用JRE1.3.0_01(JAVA運行環境1.3.0.1版本)以取代IE的JVM(JAVA虛擬機),可以到WWW.JAVA.SUN.COM網站上去
下載,下載好了先在客戶端安裝好,安裝過程非常簡單。
在服務器端的調用APPLET的HTML文件中也需要將它包含進來,以便沒有事先安裝JRE的客戶端下載,具體的寫法,請接著往下看;
具體步驟如下:
服務器端:
1.將程序需要用到的各種包文件全部解壓(我這兒要用到WEBLOGIC的JMS包使用命令jar xf
weblogicc.jar),然后使用JDK的打包命令將編譯好的監控程序.class和剛才解壓的包一起打包到一個包中。(前提我已經將監控程序和解開的包都放在同一個目錄下了),都是dos狀態下的命令,具體命令見jdk1.3(1.2)的bin目錄下,命令如下:
jar cvf monitor.jar *.class
此命令生成一個名為monitor.jar的包
2.為剛才創建的包文件(monitor.jar)創建keystore和keys。其中keystore將用來存放密匙(private keys)和公共鑰匙的認證,alias別名這兒取為monitor。
命令如下:
keytool -genkey -keystore monitor.keystore –alias monitor
此命令生成了一個名為monitor.keystore的keystore文件,接著這條命令,系統會問你好多問題,比如你的公司名稱,你的地址,你要設定的密碼等等,都由自己的隨便寫。
3.使用剛才生成的鑰匙來對jar文件進行簽名
命令如下:
jarsigner -keystore monitor.keystore monitor.jar monitor
這個命令將對monitor.jar文件進行簽名,不會生成新文件。
4.將公共鑰匙導入到一個cer文件中,這個cer文件就是要拷貝到客戶端的唯一文件
。
命令如下:
keytool -export -keystore monitor.keystore -alias monitor -file
monitor.cer
此條命令將生成monitor.cer認證文件,當然這幾步都有可能問你剛才設置的密碼。
這樣就完成了服務器端的設置。這時你就可以將jar文件和keystore文件以及cer文件(我這兒是monitor.jar,monitor.keystore,monitor.cer)拷貝到服務器的目錄下了,我用的是weblogic6.0,所以就拷貝到C:eawlserver6.0configmydomainapplicationsDefaultWebApp_myserver下的自己建的一個目錄下了。
客戶端:
1. 首先應該安裝jre1.3.0_01,然后將服務器端生成的monitor.cer文件拷貝到jre的特定目錄下,我這兒是:
c:program filesjavasoftjre1.3.0_01libsecurity目錄下。
2. 將公共鑰匙倒入到jre的cacerts(這是jre的默認keystore)
命令如下:
keytool -import -alias monitor -file monitor.cer
-keystore cacerts
注意這兒要你輸入的是cacerts的密碼,應該是changeit,而不是你自己設定的keystore的密碼。
3. 修改policy策略文件,在dos狀態下使用命令 policytool系統會自動彈出一個policytool的對話框,如圖4所示,在這里面首先選擇file菜單的open項,
打開c:program
filesjavasoftjre1.3.0_01libsecurity目錄下的java.poliy文件,然
后在edit菜單中選擇Change keystore ,在對話框中new keystore url:中輸入file:/c:/program files /javasoft/jre/1.3.0_01/lib/security/cacerts,這兒要注意反斜杠,在new keystore type中輸入JKS,這是cacerts的固定格式,然后單擊Add PolicyEntry,在出現的對話框中CodeBase中輸入:
http://URL:7001/*
其中的URL是服務器的IP地址,7001是我的weblogic的端口,如果你是在別的應用服務器上比如說是apache,那端口號就可以省略掉。在SignedBy中輸入(別名alias):這兒是Monitor然后單擊add peimission按鈕,在出現的對話框中permission中選擇你想給這個applet的權限,這兒具體有許多權限,讀者可以自己找資料看看。我這兒就選用allpeimission,右邊的signedBy中輸入別名:monitor最后保存,在file菜單的save項。當然你可以看見我已經對多個包實現了簽名認證。
這樣客戶端的設置就完成了。在客戶端用ie運行該applet程序時,會詢問你是不是對該簽名授權,選擇授權后,包會自動從服務器下載到本地計算機,而且ie會自動啟動jre,在右下欄中可以看見,相當于ie的java控制臺。
4.調用applet的html文件
大家都知道由于java2的安全性,對applet的正常調用的html文件已經不能再使用了,而改為ActiveX類型的調用。具體的又分ie和nescape的不同寫法,這一些在sun網上都能找到現成的教程。我就不多說了,只是將我的這個小程序為ie寫的的html給大家看看。
<html>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=gb2312">
<center>
<h3>消息中心實時監控平臺</h3>
<hr>
<OBJECT classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"
width="900" height="520" align="baseline"
codebase="http://192.168.2.217:7001/j2re-1_3_0_01-win-i.exe#Version=1,3,0,0">
<PARAM NAME="java_code" VALUE="wise.monitor.applet.monitorApplet">
<PARAM NAME="java_codebase" VALUE="monitor/classes">
<PARAM NAME="java_type" VALUE="application/x-java-applet;version=1.3">
<PARAM NAME="ARCHIVE" VALUE="monitor.jar" >
<PARAM NAME="scriptable" VALUE="true">
</OBJECT>
</center>
</html>
其中我要強調一點,因為applet每一次的改動都需要重新打包簽名,手續非常繁瑣,所以在具體的實現中要將一些會變化參數放到html文件中來,傳到applet中去,這一點網上文章好多,自己去看吧。
另外一個就是有朋友問我,那這樣不是太麻煩了,每一個客戶端都要進行復雜的dos命令操作,我只能說一目前我的水平只能將一個已經做好的客戶端文件cer文件和java.policy以及cacerts文件直接拷貝到客戶端,當然這也有
缺陷,如果別人的計算機已經有了認證,就會丟失。就這些問題我們可以一起探討。
另外還有一點優化,就是在打包的時候,我這兒只講了把所有要用的涉及到安全性的包和源程序到要打到一個包中。這樣如果包非常大的話,會非常影響下載的速度,如果可以使用本地計算機的包就好了,這一點jre也做到了,具體的要到控制面板的jre控制臺上去設置。這個就留著讀者自己去摸索吧。
來自:humanc2d4, 時間:2003-5-16 14:47:00, ID:1867304
我說一下JAVA控制EXCEL的方法之一。(BORLAND.COM)
使用Windows操作系統的朋友對Excel(電子表格)一定不會陌生,但是要使用Java語言來操縱Excel文件并不是一件容易的事。在Web應用日益盛行的今天,通過Web來操作Excel文件的
需求越來越強烈,目前較為流行的操作是在JSP或Servlet 中創建一個CSV (comma separated values)文件,并將這個文件以
MIME,text/csv類型返回給瀏覽器,接著瀏覽器調用Excel并且顯示CSV文件。這樣只是說可以訪問到Excel文件,但是還不能真正的操縱Excel文件,本文將給大家一個驚喜,向大家介紹一個開放源碼項目??Java Excel API,使用它大家就可以方便地操縱Excel文件了。
JAVA EXCEL API簡介
Java Excel是一開放源碼項目,通過它Java開發人員可以讀取Excel文件的內容、創建新的Excel文件、更新已經存在的Excel文件。使用該API非Windows操作系統也可以通過純Java應用來處理Excel數據表。因為是使用Java編寫的,所以我們在Web應用中可以通過JSP、Servlet來調用API實現對Excel數據表的訪問。 現在發布的穩定版本是V2.0,提供以下功能:
? 從Excel 95、97、2000等格式的文件中讀取數據;
? 讀取Excel公式(可以讀取Excel 97以后的公式);
? 生成Excel數據表(格式為Excel 97);
? 支持字體、數字、日期的格式化;
? 支持單元格的陰影操作,以及顏色操作;
? 修改已經存在的數據表;
? 現在還不支持以下功能,但不久就會提供了:
? 不能夠讀取圖表信息;
可以讀,但是不能生成公式,任何類型公式最后的計算值都可以讀出;
應用示例
從Excel文件讀取數據表
Java Excel API既可以從本地文件系統的一個文件(.xls),也可以從輸入流中讀取Excel數據表。讀取Excel數據表的第一步是創建Workbook(術語:工作薄),下面的代碼片段舉例說明了應該如何操作:(完整代碼見ExcelReading.java)
import java.io.*;
import jxl.*;
… … … …
try
{
//構建Workbook對象, 只讀Workbook對象
//直接從本地文件創建Workbook
//從輸入流創建Workbook
InputStream is = new FileInputStream(sourcefile);
jxl.Workbook rwb = Workbook.getWorkbook(is);
}
catch (Exception e)
{
e.printStackTrace();
}
一旦創建了Workbook,我們就可以通過它來訪問Excel Sheet(術語:工作表)。參考下面的代碼片段:
//獲取第一張Sheet表
Sheet rs = rwb.getSheet(0);
我們既可能通過Sheet的名稱來訪問它,也可以通過下標來訪問它。如果通過下標來訪問的話,要注意的一點是下標從0開始,就像數組一樣。
一旦得到了Sheet,我們就可以通過它來訪問Excel Cell(術語:單元格)。參考下面的代碼片段:
//獲取第一行,第一列的值
Cell c00 = rs.getCell(0, 0);
String strc00 = c00.getContents();
//獲取第一行,第二列的值
Cell c10 = rs.getCell(1, 0);
String strc10 = c10.getContents();
//獲取第二行,第二列的值
Cell c11 = rs.getCell(1, 1);
String strc11 = c11.getContents();
System.out.println("Cell(0, 0)" + " value : " + strc00 + "; type : " +
c00.getType());
System.out.println("Cell(1, 0)" + " value : " + strc10 + "; type : " +
c10.getType());
System.out.println("Cell(1, 1)" + " value : " + strc11 + "; type : " +
c11.getType());
如果僅僅是取得Cell的值,我們可以方便地通過getContents()方法,它可以將任何類型的Cell值都作為一個字符串返回。示例代碼中Cell(0, 0)是文本型,Cell(1, 0)是數字型,Cell(1,1)是日期型,通過getContents(),三種類型的返回值都是字符型。
如果有需要知道Cell內容的確切類型,API也提供了一系列的方法。參考下面的代碼片段:
String strc00 = null;
double strc10 = 0.00;
Date strc11 = null;
Cell c00 = rs.getCell(0, 0);
Cell c10 = rs.getCell(1, 0);
Cell c11 = rs.getCell(1, 1);
if(c00.getType() == CellType.LABEL)
{
LabelCell labelc00 = (LabelCell)c00;
strc00 = labelc00.getString();
}
if(c10.getType() == CellType.NUMBER)
{
NmberCell numc10 = (NumberCell)c10;
strc10 = numc10.getValue();
}
if(c11.getType() == CellType.DATE)
{
DateCell datec11 = (DateCell)c11;
strc11 = datec11.getDate();
}
System.out.println("Cell(0, 0)" + " value : " + strc00 + "; type : " +
c00.getType());
System.out.println("Cell(1, 0)" + " value : " + strc10 + "; type : " +
c10.getType());
System.out.println("Cell(1, 1)" + " value : " + strc11 + "; type : " +
c11.getType());
在得到Cell對象后,通過getType()方法可以獲得該單元格的類型,然后與API提供的基本類型相匹配,強制轉換成相應的類型,最后調用相應的取值方法getXXX(),就可以得到確定類型的值。API提供了以下基本類型,與Excel的數據格式相對應。
每種類型的具體意義,請參見Java Excel API Document。
當你完成對Excel電子表格數據的處理后,一定要使用close()方法來關閉先前創建的對象,以釋放讀取數據表的過程中所占用的內存空間,在讀取大量數據時顯得尤為重要。參考如下代碼片段:
//操作完成時,關閉對象,釋放占用的內存空間
rwb.close();
Java Excel API提供了許多訪問Excel數據表的方法,在這里我只簡要地介紹幾個常用的方法,其它的方法請參考附錄中的Java Excel API Document。
? Workbook類提供的方法
1. int getNumberOfSheets()
獲得工作?。╓orkbook)中工作表(Sheet)的個數,示例:
jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile));
int sheets = rwb.getNumberOfSheets();
2. Sheet[] getSheets()
返回工作?。╓orkbook)中工作表(Sheet)對象數組,示例:
jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile));
Sheet[] sheets = rwb.getSheets();
3. String getVersion()
返回正在使用的API的版本號,好像是沒什么太大的作用。
jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile));
String apiVersion = rwb.getVersion();
? Sheet接口提供的方法
1. String getName()
獲取Sheet的名稱,示例:
jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile));
jxl.Sheet rs = rwb.getSheet(0);
String sheetName = rs.getName();
2. int getColumns()
獲取Sheet表中所包含的總列數,示例:
jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile));
jxl.Sheet rs = rwb.getSheet(0);
int rsColumns = rs.getColumns();
3. Cell[] getColumn(int column)
獲取某一列的所有單元格,返回的是單元格對象數組,示例:
jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile));
jxl.Sheet rs = rwb.getSheet(0);
Cell[] cell = rs.getColumn(0);
4. int getRows()
獲取Sheet表中所包含的總行數,示例:
jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile));
jxl.Sheet rs = rwb.getSheet(0);
int rsRows = rs.getRows();
5. Cell[] getRow(int row)
獲取某一行的所有單元格,返回的是單元格對象數組,示例子:
jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile));
jxl.Sheet rs = rwb.getSheet(0);
Cell[] cell = rs.getRow(0);
6. Cell getCell(int column, int row)
獲取指定單元格的對象引用,需要注意的是它的兩個參數,第一個是列數,第二個是行數,這與通常的行、列組合有些不同。
jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile));
jxl.Sheet rs = rwb.getSheet(0);
Cell cell = rs.getCell(0, 0);
生成新的Excel工作薄
下面的代碼主要是向大家介紹如何生成簡單的Excel工作表,在這里單元格的內容是不帶任何修飾的(如:字體,顏色等等),所有的內容都作為字符串寫入。(完整代碼見ExcelWriting.java)
與讀取Excel工作表相似,首先要使用Workbook類的工廠方法創建一個可寫入的工作薄(Workbook)對象,這里要注意的是,只能通過API提供的工廠方法來創建Workbook,而不能使用WritableWorkbook的構造函數,因為類WritableWorkbook的構造函數為protected類型。示例代碼片段如下:
import java.io.*;
import jxl.*;
import jxl.write.*;
… … … …
try
{
//構建Workbook對象, 只讀Workbook對象
//Method 1:創建可寫入的Excel工作薄
jxl.write.WritableWorkbook wwb = Workbook.createWorkbook(new File(targetfile));
//Method 2:將WritableWorkbook直接寫入到輸出流
/*
OutputStream os = new FileOutputStream(targetfile);
jxl.write.WritableWorkbook wwb = Workbook.createWorkbook(os);
*/
}
catch (Exception e)
{
e.printStackTrace();
}
API提供了兩種方式來處理可寫入的輸出流,一種是直接生成本地文件,如果文件名不帶全路徑的話,缺省的文件會定位在當前目錄,如果文件名帶有全路徑的話,則生成的Excel文件則會定位在相應的目錄;另外一種是將Excel對象直接寫入到輸出流,例如:用戶通過瀏覽器來訪問Web服務器,如果HTTP頭設置正確的話,瀏覽器自動調用客戶端的Excel應用程序,來顯示動態生成的Excel電子表格。
接下來就是要創建工作表,創建工作表的方法與創建工作薄的方法幾乎一樣,同樣是通過工廠模式方法獲得相應的對象,該方法需要兩個參數,一個是工作表的名稱,另一個是工作表在工作薄中的位置,參考下面的代碼片段:
file://創建Excel工作表
jxl.write.WritableSheet ws = wwb.createSheet("Test Sheet 1", 0);
"這鍋也支好了,材料也準備齊全了,可以開始下鍋了!",現在要做的只是實例化API所提供的Excel基本數據類型,并將它們添加到工作表中就可以了,參考下面的代碼片段:
file://1/.添加Label對象
jxl.write.Label labelC = new jxl.write.Label(0, 0, "This is a Label cell");
ws.addCell(labelC);
//添加帶有字型Formatting的對象
jxl.write.WritableFont wf = new jxl.write.WritableFont(WritableFont.TIMES, 18,
WritableFont.BOLD, true);
jxl.write.WritableCellFormat wcfF = new jxl.write.WritableCellFormat(wf);
jxl.write.Label labelCF = new jxl.write.Label(1, 0, "This is a Label Cell", wcfF);
ws.addCell(labelCF);
//添加帶有字體顏色Formatting的對象
jxl.write.WritableFont wfc = new jxl.write.WritableFont(WritableFont.ARIAL, 10,
WritableFont.NO_BOLD, false,
UnderlineStyle.NO_UNDERLINE, jxl.format.Colour.RED);
jxl.write.WritableCellFormat wcfFC = new jxl.write.WritableCellFormat(wfc);
jxl.write.Label labelCFC = new jxl.write.Label(1, 0, "This is a Label Cell", wcfFC);
ws.addCell(labelCF);
//2.添加Number對象
jxl.write.Number labelN = new jxl.write.Number(0, 1, 3.1415926);
ws.addCell(labelN);
//添加帶有formatting的Number對象
jxl.write.NumberFormat nf = new jxl.write.NumberFormat("#.##");
jxl.write.WritableCellFormat wcfN = new jxl.write.WritableCellFormat(nf);
jxl.write.Number labelNF = new jxl.write.Number(1, 1, 3.1415926, wcfN);
ws.addCell(labelNF);
//3.添加Boolean對象
jxl.write.Boolean labelB = new jxl.write.Boolean(0, 2, false);
ws.addCell(labelB);
//4.添加DateTime對象
jxl.write.DateTime labelDT = new jxl.write.DateTime(0, 3, new java.util.Date());
ws.addCell(labelDT);
//添加帶有formatting的DateFormat對象
jxl.write.DateFormat df = new jxl.write.DateFormat("dd MM yyyy hh:mm:ss");
jxl.write.WritableCellFormat wcfDF = new jxl.write.WritableCellFormat(df);
jxl.write.DateTime labelDTF = new jxl.write.DateTime(1, 3, new java.util.Date(), wcfDF);
ws.addCell(labelDTF);
這里有兩點大家要引起大家的注意。第一點,在構造單元格時,單元格在工作表中的位置就已經確定了。一旦創建后,單元格的位置是不能夠變更的,盡管單元格的內容是可以改變的。第二點,單元格的定位是按照下面這樣的規律(column, row),而且下標都是從0開始,例如,A1被存儲在(0, 0),B1被存儲在(1, 0)。
最后,不要忘記關閉打開的Excel工作薄對象,以釋放占用的內存,參見下面的代碼片段:
file://寫入Exel工作表
wwb.write();
//關閉Excel工作薄對象
wwb.close();
這可能與讀取Excel文件的操作有少少不同,在關閉Excel對象之前,你必須要先調用write()方法,因為先前的操作都是存儲在緩存中的,所以要通過該方法將操作的內容保存在文件中。如果你先關閉了Excel對象,那么只能得到一張空的工作薄了。
拷貝、更新Excel工作薄
接下來簡要介紹一下如何更新一個已經存在的工作薄,主要是下面二步操作,第一步是構造只讀的Excel工作薄,第二步是利用已經創建的Excel工作薄創建新的可寫入的Excel工作薄,參考下面的代碼片段:(完整代碼見ExcelModifying.java)
file://創建只讀的Excel工作薄的對象
jxl.Workbook rw = jxl.Workbook.getWorkbook(new File(sourcefile));
//創建可寫入的Excel工作薄對象
jxl.write.WritableWorkbook wwb = Workbook.createWorkbook(new File(targetfile), rw);
//讀取第一張工作表
jxl.write.WritableSheet ws = wwb.getSheet(0);
//獲得第一個單元格對象
jxl.write.WritableCell wc = ws.getWritableCell(0, 0);
//判斷單元格的類型, 做出相應的轉化
if(wc.getType() == CellType.LABEL)
{
Label l = (Label)wc;
l.setString("The value has been modified.");
}
//寫入Excel對象
wwb.write();
//關閉可寫入的Excel對象
wwb.close();
//關閉只讀的Excel對象
rw.close();
之所以使用這種方式構建Excel對象,完全是因為效率的原因,因為上面的示例才是API的主要應用。為了提高
性能,在讀取工作表時,與數據相關的一些輸出信息,所有的格式信息,如:字體、顏色等等,是不被處理的,因為我們的目的是獲得行數據的值,既使沒有了修飾,也不會對行數據的值產生什么影響。唯一的不利之處就是,在內存中會同時保存兩個同樣的工作表,這樣當工作表體積比較大時,會占用相當大的內存,但現在好像內存的大小并不是什么關鍵因素了。
一旦獲得了可寫入的工作表對象,我們就可以對單元格對象進行更新的操作了,在這里我們不必調用API提供的add()方法,因為單元格已經于工作表當中,所以我們只需要調用相應的setXXX()方法,就可以完成更新的操作了。
盡單元格原有的格式化修飾是不能去掉的,我們還是可以將新的單元格修飾加上去,以使單元格的內容以不同的形式表現。
新生成的工作表對象是可寫入的,我們除了更新原有的單元格外,還可以添加新的單元格到工作表中,這與示例2的操作是完全一樣的。
最后,不要忘記調用write()方法,將更新的內容寫入到文件中,然后關閉工作薄對象,這里有兩個工作薄對象要關閉,一個是只讀的,另外一個是可寫入的。
下面是在一個Excel表格中創建一個矩陣的簡單例子:
import org.apache.poi.hssf.usermodel.*;
import java.io.FileOutputStream;
// code run against the jakarta-poi-1.5.0-FINAL-20020506.jar.
public class PoiTest {
static public void main(String[] args) throws Exception {
FileOutputStream fos = new FileOutputStream("foo.xls");
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet s = wb.createSheet();
wb.setSheetName(0, "Matrix");
for(short i=0; i<50; i++) {
HSSFRow row = s.createRow(i);
for(short j=0; j<50; j++) {
HSSFCell cell = row.createCell(j);
cell.setCellValue(""+i+","+j);
}
}
wb.write(fos);
fos.close();
}
}
這段代碼首先創建一個Workbook,從該Workbook中得到一個表格、命名,然后繼續寫入一個50x50的矩陣。最后輸出到一個名為foo.xls的Excel文件,甚至在Apple Mac機上也可以打開。
POI項目是Java應用的令人興奮的一步,為用戶提供了Windows文檔集成的新功能,允許Java開發人員方便地擴展其產品的功能。
來自:humanc2d4, 時間:2003-5-16 14:49:00, ID:1867310
我說一下JAVA中收發EMAIL的方法(轉載自:Java愛好者)
本文將討論如何用Java來編寫可根據SMTP和POP3協議來收發E-mail的Java Applet。
一.Java網絡編程初步
1.建立TCP/IP連接
Socket類中的構造函數Socket(String host,int port)用于創建一個Socket,并與指定的主機(host)及端口(port)連接。由于受到Java Applet安全機制的限制,主機名不可以任意指定,而應和被調用的Applet所在主機的名字相同。因此,可先由GetCodeBase方法取得瀏覽器當前讀取的CLASS文件所在的URL,再通過GetHost方法從該URL返回用字符串表示的該主機的名稱。例如從 http://person.zj.cninfo.net/~caveman/ 這個URL中可以返回用字符串表示的主機名"person.zj.cninfo.net"。
關于標準端口地址的值一般是:SMTP為25、POP3為110、FTP為21等,當然也有的主機用的是非標準的端口,在使用之前最好先確定一下。
2.數據的發送與接收
使用Socket類中的GetOutputStream方法可以取得與當前Socket對應的輸出數據流,用DataOutputStream類中的WriteBytes方法可以逐個字符地將數據寫入到輸出數據流中。
使用Socket類中的GetInputStream方法可以取得與當前Socket對應的輸入數據流,用DataInputStream類中的ReadLine方法可以逐行地讀取輸入數據流中的數據。
3.關閉TCP/IP連接
可以用Socket類中的close方法來關閉TCP/IP連接。
二.基于SMTP協議發送E-mail的Java Applet
1.SMTP協議和服務器
SMTP(Simple Mail Transfer Protocol)協議是目前網上流行的發送E-mail的協議,SMTP協議共有14條命令。不過,發一封E-mail只需用如下5條命令就足夠了(見表1)。
表1
命 令 功 能
HELO <SP> <domain> <CRLF> 與SMTP服務器握手,傳送本機域名
MAIL <SP> FROM:<reverse-path> <CRLF>傳送發信者的信箱名稱
RCPT <SP> TO:<forward-path> <CRLF> 傳送接收者的信箱名稱
DATA <CRLF> 發送信件數據(包括信頭和信體)
QUIT <CRLF> 退出與SMTP服務器的連接
除了ISP提供的SMTP服務器以外,國內一些存放免費個人主頁的服務器的SMTP端口也是打開的,如果該服務器對外來的E-mail沒有增加RELAY限制(例如網易nease.net就有此限制),那么也可以把它當作SMTP服務器來用。如Person.zj.cninfo.net等,在這些服務器上放一個下面要編的Java Applet和調用它的htm文件,用戶就可以實現在線發送E-mail了。
2.SMTPtester.java中的主要程序
該Java Applet用了三個文本條(TextField)部件tf1、tf2和tf3,它們分別用來供用戶輸入發信者的信箱名稱、接收者的信箱名稱和信件的標題;還用了兩個文本區(TextArea)部件ta1和ta2,ta1供用戶輸入信體內容,ta2用來顯示Smtp服務器的應答信息和出錯信息等;當然還用了一個按鈕(Button)部件bu1,用戶輸入正確的信息后,用鼠標點擊一下它,信件就可以被發出去了。
事件捕獲處理程序見程序1:
public boolean handleEvent(Event event1){
if ((event1.target != bu1) || (event1.id != 1001))
/*如果不是按鈕bu1被鼠標按下*/
{
return false;
}
if ((tf1.getText().length()!= 0) && (tf2.getText().length() != 0))
/*如果發信者和收信人的信箱名稱都填好了,執行發信程序Bu1run*/
{ bu1.disable();
bu1run();
return true;
}
else{
ta2.appendText("Please give me enough information to send your email!\n");
return true;
}
?。ǔ绦?)
發送E-mail程序bu1run見程序2:
public void bu1run(){
try{
Socket socket1= new Socket(getCodeBase().getHost(),25);
/*建立與smtp服務器的連接*/
DataOutputStream dataout2= new DataOutputStream(socket1.getOutputStream());
DataInputStream dataIn3= new DataInputStream(socket1.getInputStream());
GetReply(dataIn3);
dataout2.writeBytes("HELO person.zj.cninfo.net\r\n");
/*開始按SMTP協議發信*/
GetReply(dataIn3);
dataout2.writeBytes("MAIL FROM: " + tf1.getText() + "\r\n");
GetReply(dataIn3);
dataout2.writeBytes("RCPT TO: " + tf2.getText() + "\r\n");
GetReply(dataIn3);
dataout2.writeBytes("DATA\r\n");
GetReply(dataIn3);
dataout2.writeBytes("From: " + tf1.getText() + "\r\n");
dataout2.writeBytes("To: " + tf2.getText() + "\r\n");
dataout2.writeBytes("Subject:"+tf3.getText()+"\n\n"+ta1.getText()+"\r\n.\r\n");
GetReply(dataIn3);
dataout2.writeBytes("QUIT\r\n");
GetReply(dataIn3);
socket1.close();
/*退出連接*/
bu1.enable();
return;
}
catch (java.io.IOException IOException0) /*捕獲IO錯誤*/
{
ta2.appendText("Error!\n");
bu1.enable();
return;
}
}
?。ǔ绦?)
接收服務器應答程序GetReply見程序3:
void GetReply(DataInputStream dataIn1)
{
String string2;
string2= "";
try
{
string2= dataIn1.readLine();
ta2.appendText(string2 + "\n");
}
catch (java.io.IOException IOException0)
{
ta2.appendText("Error!\n");
bu1.enable();
return;
}
}
?。ǔ绦?)
3.實例運行
在 http://person.zj.cninfo.net/~caveman 上已經放了編譯好的SMTPtester.class和調用它的smtp.htm,圖1是該Applet在運行時的畫面,這時這封信已被發往 caveman@nease.net 了!
三.基于POP3協議讀取E_mail的Java Applet
1.POP3協議和服務器
POP3(Post Office Protocol version 3)是一種常用的網絡協議,用于從遠程服務器的信箱里收取E_mail,它的常用命令根據連接時的不同狀態有:
(1)授權狀態(AUTHORIZATION state)
User<SP><name><CRLF> 用戶名
Pass<SP><string><CRLF> 用戶密碼
Quit<CRLF> 退出
(2)執行狀態(TRANSACTION state)
STAT<CRLF> 信箱狀態,即信箱內共有幾封信,總共大?。?進制表示)等。
LIST<SP><msg><CRLF> 不用msg參數時顯示每封信的大小列表,用msg參數時顯示編號為msg的信件的長度(8進制表示)。
TOP<SP><msg><SP><n><CRLF> 取編號為msg的信件的信頭(head)和部分信體(body),n=0時只取信頭,n≠0時取信頭和信體的前n行。該命令為可選命令,有些POP3服務器軟件不支持它。
RETR<SP><msg><CRLF> 讀取編號為msg的信件。
DELE<SP><msg><CRLF> 刪編號為msg的信件,其實只是作個標記,真正刪除要到更新狀態。
(3)更新狀態(UPDATE state)
QUIT<CRLF> 退出并把做過DELE標記的郵件刪掉。
另外還有NOOP、LAST、RSET、RPOP等命令用得較少。
與SMTP服務器的情況相似,除了ISP提供的POP3服務器外,國內的一些存放免費個人主頁的服務器也提供POP3服務(例如網易nease.net)。用戶在獲得免費主頁的同時也可以得到一個POP3信箱,例如我的信箱為 caveman@nease.net ,在服務器上放一個下面要編寫的Applet和調用它的htm文件,在線運行它,輸入正確的用戶名和密碼后就可以讀取E-mail了。
2.POP3tester.java中的主要程序
該Java Applet共用了三個文本條(TextField)部件tf1、tf2和tf3,它們分別用來供用戶輸入用戶名、密碼和要讀取的E-mail的編號(為0時,只取信箱狀態不讀信);還用了一個文本區(TextArea)部件ta2,用來顯示POP3服務器的應答信息、信件內容和出錯信息等;當然還用了一個按鈕(Button)部件bu1,用戶輸入正確的信息后,用鼠標點擊一下它,就可以讀取指定的信件了。
事件捕獲處理程序與SMTPtester中的一樣,讀取E-mail程序bu1run見程序4:
public void bu1run()
{
try
{
Socket socket1= new Socket(getCodeBase().getHost(), 110);
/*連接POP3服務器*/
DataOutputStream dataout2= new DataOutputStream(socket1.getOutputStream());
DataInputStream dataIn3= new DataInputStream(socket1.getInputStream());
GetReply(dataIn3);
dataout2.writeBytes("USER" + tf1.getText() + "\r\n");
GetReply(dataIn3);
dataout2.writeBytes("PASS" + tf2.getText() + "\r\n");
GetReply(dataIn3);
dataout2.writeBytes("STAT\r\n");
/*信箱狀態*/
GetReply(dataIn3);
dataout2.writeBytes("LIST\r\n");
/*信件長度列表*/
GetReply2(dataIn3);
ta2.appendText("\n");
if (tf3.getText().equals("0") == false)
{
dataout2.writeBytes("RETR" + tf3.getText() + "\r\n");
/*讀取指定信件*/
GetReply2(dataIn3);
ta2.appendText("\n");
}
dataout2.writeBytes("QUIT\r\n");
GetReply(dataIn3);
socket1.close();
bu1.enable();
return;
}
catch (java.io.IOException IOException0)
{
ta2.appendText("Error!\n");
bu1.enable();
return;
}
}
?。ǔ绦?)
接收服務器應答程序GetReply和GetReply2見程序5:
void GetReply2(DataInputStream dataIn1)
{
String string2;
string2= "";
try
{
for (string2=dataIn1.readLine();
(string2.equals(".")=false);
string2=dataIn1.readLine())
/*List和Retr命令的應答雖然有多行,但都用一句"."作為結束,可據此取應答信息*/
{
ta2.appendText(string2 + "\n");
}
}
catch (java.io.IOException IOException0)
{
ta2.appendText("Error!\n");
bu1.enable();
return;
}
}
?。ǔ绦?)
讀取單句應答的程序GetReply和SMTPtester中的相同,因為在與POP3服務器對話時,List和Retr的應答不只一句,因此又編了一個GetReply2程序來處理這個問題。
3.實例運行
在 http://www.netease.com/~caveman 上已經放了編譯好的POP3tester.class和調用它的POP3.html,圖2是該Applet運行時的畫面,剛才在person.zj.cninfo.net上用SMTPtester發出的那封信已到了我網易的信箱里了。
四.程序的改進
以上兩個Java Applet還很不完善,在加強錯誤捕獲、對郵件附件的支持等方面需要改進的地方還很多。另外,根據上面提到的一些基本方法,只需稍加變化,還可以用Java來實現其他網絡協議,如FTP、NEWS等
原文轉自:http://www.anti-gravitydesign.com