????? import com.sun.image.codec.jpeg.JPEGCodec;
????? import com.sun.image.codec.jpeg.JPEGImageEncoder;
?????
????? public class JpgTest {
?
?public void JpgTset() throws Exception{
???? File _file = new File("/Order005-0001.jpg");?????????????????????? //讀入文件
???? Image src = javax.imageio.ImageIO.read(_file);???????????????????? //構(gòu)造Image對象
???? int wideth=src.getWidth(null);???????????????????????????????????? //得到源圖寬
???? int height=src.getHeight(null);??????????????????????????????????? //得到源圖長
???? BufferedImage tag = new BufferedImage(wideth/2,height/2,BufferedImage.TYPE_INT_RGB);
???? tag.getGraphics().drawImage(src,0,0,wideth/2,height/2,null);?????? //繪制縮小后的圖
???? FileOutputStream out=new FileOutputStream("newfile.jpg");????????? //輸出到文件流
???? JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);??????
???? encoder.encode(tag);?????????????????????????????????????????????? //近JPEG編碼
???? //System.out.print(width+"*"+height);?????????????????????????????
???? out.close();
?}
????? }
???
??? 過程很簡單,從本地磁盤讀取文件Order005-0001.jpg(2032*1524),變成Image對象src,接著構(gòu)造目標(biāo)文件tag,設(shè)置tag的長寬為源圖的一半,對tag進(jìn)行編碼,輸出到文件流out,最后關(guān)閉文件流。
???
??? 還有一些問題需要說明:
??? 第一,目前只能支持JPG(JPEG)、GIF、PNG三種格式。(這里有些問題,在最下面解釋)
??? 第二,對于源圖的容量有限制,最好不要超過1M,否則會(huì)拋內(nèi)存不足的錯(cuò)誤,不過我試驗(yàn)過1.8M的源圖,可以成功,但是也很容易拋內(nèi)存不足。
???
??? 引用一位前輩的話:圖象運(yùn)算本身是密集型運(yùn)算,需要大量的內(nèi)存存放象素值。我用VC試了一下,4M的圖象也有問題,而且越是壓縮比大的圖片在內(nèi)存中還原成BITMAP時(shí)需要的內(nèi)存越大。解決的方法,可以重寫編碼類,先開一定的內(nèi)存,然后一段一段編碼寫到臨時(shí)文件中,輸出的時(shí)候再一段一段讀出來。或利用nio的內(nèi)存映象來操作。JavaMail由于采用了Builder模式,先生成一個(gè)郵件的每一個(gè)部分,然后合并成一個(gè)完整的郵件對象,這樣每個(gè)構(gòu)件都要先生成到內(nèi)存中,你如果發(fā)送一個(gè)上百兆的附件,那么在構(gòu)造Part時(shí)肯定內(nèi)存溢出,所以我就改寫了BodyPart的構(gòu)造,讓他和一個(gè)臨時(shí)文件關(guān)聯(lián),然后用臨時(shí)文件保存Part而不是構(gòu)造在內(nèi)存中,這樣任義大小的附件(硬盤能放得下為限)都可以發(fā)送了。
???
??? 最后,如果大家對圖像處理有更高的要求,不妨關(guān)注一下開源項(xiàng)目。比如JMagick,可以使用JMagick來實(shí)現(xiàn)圖片的復(fù)制、信息獲取、斜角、特效、組合、改變大小、加邊框、旋轉(zhuǎn)、切片、改變格式、去色等等功能。
2007-06-20更新
其實(shí)按照上面的做法只能壓縮jpg格式,gif是不能壓縮的(由于算法版權(quán)問題,直到Java 6.0才能壓縮gif),前段時(shí)間要用gif壓縮,在網(wǎng)上找了個(gè)類,可以解決問題。請參考:http://mindprod.com/jgloss/gifencoder.html。
替換以前代碼的相應(yīng)部分:
當(dāng)代碼運(yùn)行完畢,用EditPlus之類的文本編輯器打開之后可以發(fā)現(xiàn)文件頭已經(jīng)是gif87格式了。
請注意!引用、轉(zhuǎn)貼本文應(yīng)注明原作者:Rosen Jiang 以及出處:http://www.aygfsteel.com/rosen
面向服務(wù)體系
SOA (面向服務(wù)體系)是近期推動(dòng)應(yīng)用和業(yè)務(wù)集成領(lǐng)域產(chǎn)生巨大飛躍的新技術(shù)之一。 SOA 定義了一系列詳盡的體系規(guī)范、范例和實(shí)現(xiàn)應(yīng)用程序間進(jìn)行松散耦合交互的最佳準(zhǔn)則。
SOA 基于定義明確的接口,促進(jìn)多個(gè)應(yīng)用程序間的松散耦合交互。服務(wù)的實(shí)現(xiàn)是獨(dú)立的,且不依賴上下文信息以及其他服務(wù)的狀態(tài)。服務(wù)間數(shù)據(jù)交換主要基于文本類型的格式,使用基于標(biāo)準(zhǔn)的消息模型。服務(wù)自身并不知道服務(wù)提供者和服務(wù)消費(fèi)者之間傳輸級(jí)的通訊交互。
盡管不是強(qiáng)制要求,當(dāng)今大部分流行的基于
SOA
的系統(tǒng)都利用了
Web
服務(wù)以及近似技術(shù)為服務(wù)間交互提供必要的管道管理。
WSDL
(
Web
服務(wù)定義語言)扮演了主要的通訊模型角色;
SOAP
扮演了消息承載協(xié)議、
HTTP
扮演了網(wǎng)絡(luò)傳輸協(xié)議。當(dāng)然,這并不意味著你必須利用上述技術(shù)實(shí)現(xiàn)基于
SOA
的系統(tǒng)。另外,有些術(shù)語之前就已經(jīng)存在了,所以很多企業(yè)已利用類似的體系實(shí)現(xiàn)了系統(tǒng)的松散耦合交互。不管怎樣,主要的不同點(diǎn)在于我們現(xiàn)在已經(jīng)有標(biāo)準(zhǔn)協(xié)議、工具集和軟件了,使面向服務(wù)體系更健全。
SOA 原則與面向?qū)ο蠓妒健⒃瓌t有著顯著不同。主要不同在于服務(wù)間交互的接口被定義了更多面向數(shù)據(jù)的行為。一個(gè)孤立的服務(wù)也許會(huì)采用面向?qū)ο笤瓌t和技術(shù),但是,服務(wù)之間的交互很少采用這些手段。相反,這些接口更適合于基于文檔的交換。面向?qū)ο蟮男袨槭墙壎〝?shù)據(jù),而面向服務(wù)從行為中分離數(shù)據(jù)。
企業(yè)服務(wù)總線
ESB (企業(yè)服務(wù)總線)為面向服務(wù)體系提供了基礎(chǔ)架構(gòu)。通過設(shè)計(jì)工具定義服務(wù)間交互和規(guī)則, ESB 為部署和發(fā)現(xiàn)服務(wù)提供了運(yùn)行時(shí)環(huán)境。
?
??? 在
ESB
的世界中,服務(wù)不會(huì)直接彼此交互。“
ESB
運(yùn)行時(shí)”作為一個(gè)仲裁者在服務(wù)間松散的耦合它們。“
ESB
運(yùn)行時(shí)”將實(shí)現(xiàn)協(xié)議綁定、消息傳輸、消息處理,等等。
一個(gè)服務(wù)總線將包括下列關(guān)鍵項(xiàng):
??? 為服務(wù)提供傳輸綁定
??? 定義和發(fā)現(xiàn)已部署服務(wù)
??? 在服務(wù)間基于規(guī)則的路由和編排消息
??? 包括文檔傳遞在內(nèi)的增值服務(wù)等
大部分的 ESB 提供商基于自己的 SOA 提議來開放標(biāo)準(zhǔn)和技術(shù),包括多種 Web 服務(wù)標(biāo)準(zhǔn)和協(xié)議。他們提供多種調(diào)用服務(wù)的傳輸綁定,包括 HTTP 、 FTP 以及 JMS 等等。大部分 ESB 用戶利用 WS-BPEL ( Web 服務(wù)的業(yè)務(wù)流程執(zhí)行語言)來了解已部署服務(wù)之間是如何實(shí)現(xiàn)業(yè)務(wù)流程的。 ESB 提供商同時(shí)也提供服務(wù)質(zhì)量特性,包括容錯(cuò)、故障轉(zhuǎn)移、負(fù)載平衡、消息緩沖等等。
Java
業(yè)務(wù)集成
???
JBI ( Java 業(yè)務(wù)集成)的提出是基于面向服務(wù)體系提倡的方法和原則,為了解決 EAI 和 B2B 若干問題的 Java 標(biāo)準(zhǔn)。當(dāng)前版本( 1.0 )是 2005 年 8 月通過的 JSR ( Java 規(guī)范需求) 208 定案。商業(yè)和開源界都?xì)g迎 JBI 成為他們 ESB 產(chǎn)品的集成標(biāo)準(zhǔn)。
基于仲裁者體系
JBI 定義了基于插件方式的架構(gòu),以便服務(wù)能融入“ JBI 運(yùn)行時(shí)”環(huán)境。 JBI 提供了詳細(xì)的接口,使服務(wù)能與“ JBI 運(yùn)行時(shí)”環(huán)境交互。這些服務(wù)要為“ JBI 運(yùn)行時(shí)”環(huán)境暴露接口,以便“ JBI 運(yùn)行時(shí)”環(huán)境為服務(wù)路由消息。“ JBI 運(yùn)行時(shí)”環(huán)境在部署在 SOA 環(huán)境中的服務(wù)間扮演仲裁者的角色。
在同一
JVM
中,“
JBI
運(yùn)行時(shí)”核心主要包括如下組件:
??? 組件框架:組件框架把不同類型的組件部署到“ JBI 運(yùn)行時(shí)”。
?? ? 歸一化消息路由器:歸一化消息路由器利用標(biāo)準(zhǔn)機(jī)制實(shí)現(xiàn)服務(wù)間消息交換。
??
?
管理框架:管理框架基于
JMX
進(jìn)行部署、管理以及監(jiān)控“
JBI
運(yùn)行時(shí)”中的組件。
組件模型
??? JBI 在“ JBI 運(yùn)行時(shí)”環(huán)境中定義了兩種組件:
??? 服務(wù)引擎組件:該組件負(fù)責(zé)實(shí)現(xiàn)業(yè)務(wù)邏輯和其他服務(wù)。服務(wù)引擎組件在其內(nèi)部可使用多種技術(shù)和設(shè)計(jì)模式。服務(wù)引擎組件可提供數(shù)據(jù)傳輸和轉(zhuǎn)換這種簡單的基礎(chǔ)服務(wù),也可實(shí)現(xiàn)像 WS-BPEL 實(shí)例一樣復(fù)雜的業(yè)務(wù)處理。
??? 綁定組件:綁定組件主要為已部署服務(wù)提供傳輸級(jí)綁定。綁定組件有多種類型:
??????? 利用標(biāo)準(zhǔn)傳輸協(xié)議與外部系統(tǒng)進(jìn)行遠(yuǎn)程通訊。
??????? 使已部署服務(wù)能在同一個(gè) JVM 內(nèi)部相互調(diào)用。
??????? 服務(wù)間可使用標(biāo)準(zhǔn)的 WS-I ( Web 服務(wù)協(xié)同工作組織)規(guī)范通訊。
??? JBI 的關(guān)鍵是分離服務(wù)引擎和綁定組件,以便業(yè)務(wù)邏輯不被下面的具體細(xì)節(jié)所干擾。這種方式促進(jìn)了體系的靈活性和可擴(kuò)展性。綁定組件和服務(wù)引擎組件在 JBI 內(nèi)部都可以是服務(wù)提供者和 / 或服務(wù)消費(fèi)者。
???
??? 綁定組件和服務(wù)引擎組件為“ JBI 運(yùn)行時(shí)”提供接口以便從“ JBI 運(yùn)行時(shí)”接收消息。同樣的,它們也利用 JBI 提供的接口來和“ JBI 運(yùn)行時(shí)”通訊。
消息傳輸模型
JBI 利用消息傳輸模型分離服務(wù)提供者和服務(wù)消費(fèi)者之間的耦合。消息傳輸模型利用了 WSDL 。 WSDL 用于描述暴露的服務(wù)引擎組件和綁定組件的業(yè)務(wù)處理。另外, WSDL 也用于定義抽象服務(wù)處理的傳輸級(jí)綁定。
JBI 架構(gòu)中一個(gè)關(guān)鍵組件是 NMR (歸一化消息路由器,也譯作“正規(guī)消息路由器”)。 NMR 基于 WSDL 提供了主要的消息傳輸中樞, NMR 為部署在“ JBI 運(yùn)行時(shí)”中的服務(wù)引擎組件和綁定組件間的消息傳遞提供松散耦合。服務(wù)需要有聚合業(yè)務(wù)處理的接口,每個(gè)業(yè)務(wù)處理由零個(gè)或多個(gè)消息組成。而一個(gè)接口有一個(gè)或多個(gè)傳輸級(jí)綁定。
“ JBI 運(yùn)行時(shí)”利用歸一化格式描述消息。一個(gè)歸一化消息由以下部分組成:
??? 消息屬性
??? 消息有效載荷
消息附件
???
利用 NMR , JBI 規(guī)范為服務(wù)提供者和消費(fèi)者的消息交換提供標(biāo)準(zhǔn)接口。 NMR 支持服務(wù)生產(chǎn)者和消費(fèi)者之間單向模式和服務(wù)響應(yīng)模式的調(diào)用。
管理
JBI 利用 JMX 實(shí)現(xiàn)運(yùn)行時(shí)的服務(wù)安裝、配置和監(jiān)控。服務(wù)必須實(shí)現(xiàn) JBI 接口集,以便這些服務(wù)在 JBI 環(huán)境中是可管理的。 JBI 環(huán)境必須提供一套 JMX MBeans 實(shí)現(xiàn)“ JBI 運(yùn)行時(shí)”的管理。
“ JBI 運(yùn)行時(shí)”環(huán)境允許服務(wù)引擎組件和綁定組件的相關(guān)操作如下:
??? 安裝組件:使組件接口可使用歸一化消息路由器。
??? 安裝 artefact 組件:這將允許已部署的 artefacts 組件獲得與已安裝組件同樣的機(jī)能。例如,可以部署一個(gè)“連接服務(wù)”來提供具體的數(shù)據(jù)庫連接。
??? 啟動(dòng)、停止服務(wù)以及進(jìn)行相關(guān)服務(wù)分組。
JBI 為組件及 artefact 組件定義了標(biāo)準(zhǔn)的部署描述符以及打包模型。
角色
JBI 為基于 JBI 的端到端 EAI 解決方案定義了如下角色:
? ?? 引擎開發(fā)者:引擎開發(fā)者提供遵循 NMR 和管理約束的服務(wù)引擎組件。
??? 綁定開發(fā)者:綁定開發(fā)者提供遵循 NMR 和管理約束的綁定組件。
JBI 環(huán)境提供者: JBI 環(huán)境提供者為“ JBI 運(yùn)行時(shí)”使用 J2EE 1.4 或 J2SE 1.4 或更新的平臺(tái)提供支持。
J2EE 平臺(tái)提供者: J2EE 平臺(tái)提供者把“ JBI 運(yùn)行時(shí)”作為提供應(yīng)用程序服務(wù)的一部分。
JBI 應(yīng)用程序開發(fā)者: JBI 應(yīng)用程序開發(fā)者利用服務(wù)引擎組件、綁定組件以及 JBI 環(huán)境構(gòu)建 JBI 應(yīng)用程序。
結(jié)論
???
???
當(dāng)今業(yè)界走向越來越開放的標(biāo)準(zhǔn)和規(guī)范,
JBI
在使
Java
技術(shù)利用面向服務(wù)體系和
ESB
基礎(chǔ)架構(gòu)實(shí)現(xiàn)業(yè)務(wù)集成方面產(chǎn)生了巨大飛躍。像
Oracle
這樣的商用產(chǎn)品提供商和
ServiceMix
這樣的開源軟件都把
JBI
作為了他們
ESB
方案的一部分。
關(guān)于作者
??? Meeraj Kinnumpurath
是位在
VOCA
有限公司(原來叫
BACS
)就職的
Java
架構(gòu)師,這家公司是英國最大的票據(jù)交換所。他有
8
年的
Java
開發(fā)經(jīng)驗(yàn),主要從事企業(yè)應(yīng)用程序開發(fā)。他已出版了一些
Java
、
J2EE
以及
Web
服務(wù)方面的書籍。
請注意!引用、轉(zhuǎn)貼本文應(yīng)注明原譯者:Rosen Jiang 以及出處:
http://www.aygfsteel.com/rosen
BIRT 應(yīng)用開發(fā)從報(bào)表設(shè)計(jì)開始。基于 Eclipse 插件提供多種快速構(gòu)建報(bào)表工具。
數(shù)據(jù)瀏覽器 - 把你的數(shù)據(jù)源(連接)以及數(shù)據(jù)集(查詢)組織起來。數(shù)據(jù)集編輯器允許你測試數(shù)據(jù)集,以確保報(bào)表接收數(shù)據(jù)的正確性。
布局視圖 - 所見即所得編輯器為你的報(bào)表提供以拽方式來創(chuàng)建表現(xiàn)內(nèi)容。包含一個(gè)標(biāo)準(zhǔn)報(bào)表?xiàng)l目調(diào)色板。
屬性編輯器 - 以便利的格局表現(xiàn)大多數(shù)通用的用戶屬性使編輯更快速和容易。BIRT 也集成了標(biāo)準(zhǔn) Eclipse 屬性視圖,為每個(gè)條目提供詳細(xì)的屬性列表。
報(bào)表預(yù)覽 - 你可以在任何時(shí)間采用真實(shí)數(shù)據(jù)測試你的報(bào)表。預(yù)覽窗口直接內(nèi)嵌在 Eclipse 中。
代碼編輯器 - 在訪問數(shù)據(jù)以及報(bào)表生成或?yàn)g覽時(shí),腳本把業(yè)務(wù)邏輯添加給報(bào)表。在編輯腳本時(shí)代碼編輯器提供標(biāo)準(zhǔn)的 Eclipse 特性:語法加色、自動(dòng)完成等等。BIRT 用很簡單的腳本來表達(dá),expression builder 能更容易的創(chuàng)建這些表達(dá)。
略圖 - BIRT 報(bào)表被組織為一個(gè)樹型結(jié)構(gòu)作為整體報(bào)表的根,并且為樣式、報(bào)表內(nèi)容、數(shù)據(jù)源、數(shù)據(jù)集、報(bào)表參數(shù)等分類。略圖視圖提供你整個(gè)報(bào)表結(jié)構(gòu)緊湊的預(yù)覽。
Cheat Sheets - 學(xué)習(xí)新工具永遠(yuǎn)是種挑戰(zhàn),但是 Eclipse 提供一種創(chuàng)新方案:cheat sheets。它們是一些幫助你完成新任務(wù)的文檔。
數(shù)據(jù)定制
正如前面所提到的,報(bào)表通常為要表現(xiàn)的數(shù)據(jù)添加業(yè)務(wù)邏輯。BIRT 提供多個(gè)工具來完成這一操作:
欄位計(jì)算-數(shù)據(jù)庫為存儲(chǔ)組織數(shù)據(jù),但這些數(shù)據(jù)通常為結(jié)合表現(xiàn)層而預(yù)先整理好。欄位計(jì)算讓你能定義基于業(yè)務(wù)邏輯的附加數(shù)據(jù)集欄位。這種邏輯是一個(gè)簡單的語法、腳本或調(diào)用一個(gè)已有的 Java 邏輯。
輸入以及輸出參數(shù)-許多數(shù)據(jù)源都支持參數(shù):在查詢時(shí)傳入或傳出數(shù)據(jù)的能力。比如,SQL Select 語句可包含輸入?yún)?shù)。存儲(chǔ)過程既有傳入又有傳出參數(shù)。
欄位元數(shù)據(jù)-當(dāng)數(shù)據(jù)源提供的名字是 unintuitive 的,你可以提供欄位別名。
過濾 - 有些數(shù)據(jù)源,尤其是 SQL,提供良好的內(nèi)置過濾特性。然而,有些數(shù)據(jù)源(單純的文件,應(yīng)用程序?qū)ο螅﹨s沒有提供過濾特性。另外,過濾器條件是定義在腳本或 Java 代碼中的。你可把過濾器定義為報(bào)表的一部分,BIRT 引擎會(huì)自動(dòng)調(diào)用它們。
腳本化數(shù)據(jù)集 - 有些報(bào)表需要訪問專門或不常用的數(shù)據(jù)。你可以在 Java 或腳本創(chuàng)建訪問,利用腳本化數(shù)據(jù)集可在報(bào)表中集成這些邏輯。
條件格式化
有些報(bào)表有著固定的格式,其他的卻需要條件格式化。例如,某報(bào)表列出了交易記錄來表現(xiàn)不同的銷售與利潤之比。或者,一個(gè)客戶服務(wù)報(bào)表要按照不同規(guī)則進(jìn)行色彩顯示。BIRT 提供多個(gè)條件格式化特性:
條件可見度 - 你可以根據(jù)數(shù)據(jù)隱藏報(bào)表元素。在上述的交易報(bào)表中,你可以創(chuàng)建銷售和交易收入兩部分,接著隱藏報(bào)表指定記錄中不需要的部分。
值映射 - 數(shù)據(jù)庫數(shù)據(jù)通常使用代碼值:M/F 代表男性或女性,1/2 代表銷售和收入,等等。值映射讓你定義一個(gè)從數(shù)據(jù)庫值到顯示值的映射。例如,我們可把值“1”對應(yīng)到“Sale”,把“2”對應(yīng)到“Return”。
加強(qiáng) - 簡單的標(biāo)識(shí)可讓你對特定報(bào)表套用樣式。例如,在客戶服務(wù)報(bào)表中,我們可以使用綠色表示上一的計(jì)劃,紅色表示下一計(jì)劃。
腳本
BIRT 提供基于 JavaScript(與知名的 ECMAScript 形式上相同)的腳本。JavaScript 經(jīng)常作為客戶端腳本語言,但是它也可以用于用于表達(dá)業(yè)務(wù)邏輯。特別的,JavaScript 能與你的現(xiàn)有 Java 邏輯進(jìn)行良好集成,能非常輕松地從 BIRT 報(bào)表調(diào)用業(yè)務(wù)邏輯。
BIRT 提供從 JavaScript 對象訪問報(bào)表對象模型(Report Object Model)的整套方案:同時(shí)表現(xiàn)報(bào)表設(shè)計(jì)和運(yùn)行時(shí)的狀況,允許報(bào)表的完全控制處理甚至最復(fù)雜的報(bào)表格式化工作。
項(xiàng)目管理
BIRT 集成了 Eclipse 項(xiàng)目管理特性來組織相關(guān)報(bào)表。BIRT 也可以與 Eclipse CVS 協(xié)作進(jìn)行源碼管理。BIRT 的 XML 報(bào)表設(shè)計(jì)格式讓它能容易的比較兩份報(bào)表,或者兩個(gè)不同版本的相同報(bào)表,并跟蹤變更。
樣式
任何設(shè)計(jì) web 頁面的人都知道有時(shí)會(huì)反復(fù)使用相同的樣式。CSS 允許 web 設(shè)計(jì)者從內(nèi)容中提取樣式信息,并復(fù)用樣式。
BIRT 提供類似的特性。當(dāng)然,BIRT 樣式也是基于 CSS 的,這樣使得網(wǎng)頁應(yīng)用開發(fā)人員能容易得設(shè)計(jì) BIRT 表現(xiàn)形式。BIRT 樣式可堆疊,允許你在一個(gè)地方設(shè)置樣式后套用到所有報(bào)表或報(bào)表的一部分或單一報(bào)表中。
庫
典型的應(yīng)用中會(huì)包括許多有關(guān)聯(lián)的報(bào)表。一個(gè)簡單的客戶應(yīng)用將包括一個(gè)按照字母排序的客戶列表、按照地理位置分類的客戶群,為客戶指定的銷售代表,客戶身份篩選等等。總之,用戶不停的地變化報(bào)表以解決具體業(yè)務(wù)需要。
這樣一來,最終的報(bào)表應(yīng)用將包含多組相關(guān)報(bào)表。相同的數(shù)據(jù)源、樣式、業(yè)務(wù)邏輯、報(bào)表?xiàng)l目。
將來的 BIRT 版本將包含組織這些共享資源的支持庫。這些庫可包含任何報(bào)表元素,比如樣式、數(shù)據(jù)源、報(bào)表?xiàng)l目、腳本等等。
國際化
全世界都可以訪問你的 web 應(yīng)用程序。BIRT 為國際化和本地化提供良好的支持。
文本本地化 - 你可以建立一份把字符串自動(dòng)變成用戶本地語言顯示的簡單報(bào)表。所有的表單和報(bào)表文本都能以標(biāo)準(zhǔn)的 Java 本地化規(guī)則進(jìn)行翻譯。在運(yùn)行時(shí),BIRT 使用資源 key 找出文本的正確翻譯。
本地化 - BIRT 提供 locale-aware 格式化數(shù)據(jù),意味著對于美國用戶的日期數(shù)據(jù)可以以 mm/dd/yy 的格式出現(xiàn),而歐洲用戶則是 dd-mm-yy 格式。
動(dòng)態(tài)格式化 - 中文文本非常緊湊,德文有時(shí)又有點(diǎn)冗長,而英文正好是中等大小。BIRT 自動(dòng)調(diào)整報(bào)表?xiàng)l目的大小來適合其中的內(nèi)容,避免每次翻譯都要進(jìn)行報(bào)表測試。
擴(kuò)展性
報(bào)表應(yīng)用程序的范圍是十分龐大的,BIRT 團(tuán)隊(duì)不能為每個(gè)應(yīng)用提供很具體的特性。可利用 BIRT 腳本來擴(kuò)展 BIRT,另外還可構(gòu)建 BIRT 擴(kuò)展插件到 BIRT 中。
數(shù)據(jù)訪問
BIRT 提供 ODA(Open Data Access) 框架來支持自定義數(shù)據(jù)訪問方法。數(shù)據(jù)訪問的范圍還包括一個(gè)獲取數(shù)據(jù)的運(yùn)行時(shí)組件。也包括構(gòu)建自定義查詢的自定義設(shè)計(jì)時(shí) UI。例如,打包后的應(yīng)用程序可以讓 ODA 構(gòu)建數(shù)據(jù)訪問 UI 并運(yùn)行在自己的數(shù)據(jù)模型中。
報(bào)表欄目
BIRT 為要表現(xiàn)的數(shù)據(jù)提供一致的報(bào)表欄目集。可以在應(yīng)用程序中自定義附件報(bào)表欄目,并像 BIRT 自身的報(bào)表欄目一樣運(yùn)行在設(shè)計(jì)器和引擎中。例如,性能管理應(yīng)用程序要添加報(bào)表欄目來高亮顯示停止項(xiàng)、尺度表以及其他用來衡量性能的可視標(biāo)志。
圖表類型
BIRT 圖表包提供了很多的圖表類型。但是,一些行業(yè)需要很特殊的圖表樣式。開發(fā)者可以在 BIRT 圖表引擎中創(chuàng)建圖表插件來提供這些圖表樣式。
輸出格式
BIRT 1.0.1 支持輸出到 HTML 和 PDF。當(dāng)然,也可能需要其他類型輸出:Excel、RTF(Rich Text Format)、SVG(Scalable Vector Graphic)、圖像、等等。BIRT 在今后會(huì)提供其中一些,除開這些的其他格式可能需要的用戶就很少了。開發(fā)者可利用 BIRT 引擎接口添加轉(zhuǎn)換器以達(dá)到目的。
請注意!引用、轉(zhuǎn)貼本文應(yīng)注明原譯者:Rosen Jiang 以及出處:http://www.aygfsteel.com/rosen
<?xml version="1.0" encoding="GBK" ?> <propertysets> <propertset name="rea_faculty" description="team"> |
為以上 XML 文件構(gòu)造 Propertys 類:
public class Propertys { private String name; private String description; private String field; public String getDescription() { public void setDescription(String description) { public String getField() { public void setField(String field) { public String getName() { public void setName(String name) { |
讀取方法(返回包含 Propertys 的列表):
public List getAll() { List list = new ArrayList(); try { InputStream is = getClass().getResourceAsStream("/navigation.xml"); SAXReader reader = new SAXReader(); Document document = reader.read(is); Element root = document.getRootElement(); Iterator lv = root.elementIterator("propertset"); Element el = null; while (lv.hasNext()) { Propertys property=new Propertys(); el = (Element) lv.next(); property.setName(el.attributeValue("name")); property.setDescription(el.attributeValue("description")); property.setField(el.elementText("field")); list.add(property); } } catch (Exception e) { e.printStackTrace(); } return list; } |
添加新節(jié)點(diǎn)(成功返回 1 否則 0):
public int saveProperty(Propertys property) { try { InputStream is = getClass().getResourceAsStream("/navigation.xml"); SAXReader reader = new SAXReader(); Document document = reader.read(is); Element root = document.getRootElement(); root.addElement("propertset") .addAttribute("name",property.getName()) .addAttribute("description",property.getDescription()) .addElement("field").addText(property.getField()); OutputFormat outformat = OutputFormat.createPrettyPrint(); outformat.setEncoding("GBK"); FileWriter out = new FileWriter( System.getProperty("user.dir") +"/web/WEB-INF/classes/navigation.xml"); XMLWriter writer=new XMLWriter(out,outformat); writer.write(document); writer.close(); return 1; } catch (Exception e) { e.printStackTrace(); } return 0; } |
更新節(jié)點(diǎn)(按照 name 屬性查找):
public int updateProperty(String pro,Propertys property) { try { InputStream is = getClass().getResourceAsStream("/navigation.xml"); SAXReader reader = new SAXReader(); Document document = reader.read(is); Element root = document.getRootElement(); Iterator lv = root.elementIterator("propertset"); Element el = null; while (lv.hasNext()) { el = (Element) lv.next(); if (el.attributeValue("name").equals(pro)) { el.setAttributeValue("name",property.getName()); el.setAttributeValue("description",property.getDescription()); el.element("field").setText(property.getField()); } } OutputFormat outformat = OutputFormat.createPrettyPrint(); |
刪除節(jié)點(diǎn):
public int delProperty(String pro) { try { InputStream is = getClass().getResourceAsStream("/navigation.xml"); SAXReader reader = new SAXReader(); Document document = reader.read(is); Element root = document.getRootElement(); Iterator lv = root.elementIterator("propertset"); Element el = null; while (lv.hasNext()) { el = (Element) lv.next(); if (el.attributeValue("name").equals(pro)) { el.detach(); } } OutputFormat outformat = OutputFormat.createPrettyPrint(); |
測試方法:
采用 JSP 端調(diào)用Bean(至于為什么采用JSP來調(diào)用,請參考:http://blog.csdn.net/rosen/archive/2004/10/15/138324.aspx),讓每一種方案分別解析10K、100K、1000K、10000K的 XML 文件,計(jì)算其消耗時(shí)間(單位:毫秒)。
JSP 文件:
<%@ page contentType="text/html; charset=gb2312" %>
<%@ page import="com.test.*"%>
<html>
<body>
<%
String args[]={""};
MyXMLReader.main(args);
%>
</body>
</html>
測 試
首先出場的是 DOM(JAXP Crimson 解析器)
DOM 是用與平臺(tái)和語言無關(guān)的方式表示 XML 文檔的官方 W3C 標(biāo)準(zhǔn)。DOM 是以層次結(jié)構(gòu)組織的節(jié)點(diǎn)或信息片斷的集合。這個(gè)層次結(jié)構(gòu)允許開發(fā)人員在樹中尋找特定信息。分析該結(jié)構(gòu)通常需要加載整個(gè)文檔和構(gòu)造層次結(jié)構(gòu),然后才能做任何工作。由于它是基于信息層次的,因而 DOM 被認(rèn)為是基于樹或基于對象的。DOM 以及廣義的基于樹的處理具有幾個(gè)優(yōu)點(diǎn)。首先,由于樹在內(nèi)存中是持久的,因此可以修改它以便應(yīng)用程序能對數(shù)據(jù)和結(jié)構(gòu)作出更改。它還可以在任何時(shí)候在樹中上下導(dǎo)航,而不是像 SAX 那樣是一次性的處理。DOM 使用起來也要簡單得多。
另一方面,對于特別大的文檔,解析和加載整個(gè)文檔可能很慢且很耗資源,因此使用其他手段來處理這樣的數(shù)據(jù)會(huì)更好。這些基于事件的模型,比如 SAX。
Bean文件:
package com.test;
import java.io.*;
import java.util.*;
import org.w3c.dom.*;
import javax.xml.parsers.*;
public class MyXMLReader{
public static void main(String arge[]){
long lasting =System.currentTimeMillis();
try{
File f=new File("data_10k.xml");
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
DocumentBuilder builder=factory.newDocumentBuilder();
Document doc = builder.parse(f);
NodeList nl = doc.getElementsByTagName("VALUE");
for (int i=0;i<nl.getLength();i++){
System.out.print("車牌號(hào)碼:" + doc.getElementsByTagName("NO").item(i).getFirstChild().getNodeValue());
System.out.println(" 車主地址:" + doc.getElementsByTagName("ADDR").item(i).getFirstChild().getNodeValue());
}
}catch(Exception e){
e.printStackTrace();
}
System.out.println("運(yùn)行時(shí)間:"+(System.currentTimeMillis() - lasting)+" 毫秒");
}
}
10k消耗時(shí)間:265 203 219 172
100k消耗時(shí)間:9172 9016 8891 9000
1000k消耗時(shí)間:691719 675407 708375 739656
10000k消耗時(shí)間:OutOfMemoryError
接著是 SAX
這種處理的優(yōu)點(diǎn)非常類似于流媒體的優(yōu)點(diǎn)。分析能夠立即開始,而不是等待所有的數(shù)據(jù)被處理。而且,由于應(yīng)用程序只是在讀取數(shù)據(jù)時(shí)檢查數(shù)據(jù),因此不需要將數(shù)據(jù)存儲(chǔ)在內(nèi)存中。這對于大型文檔來說是個(gè)巨大的優(yōu)點(diǎn)。事實(shí)上,應(yīng)用程序甚至不必解析整個(gè)文檔;它可以在某個(gè)條件得到滿足時(shí)停止解析。一般來說,SAX 還比它的替代者 DOM 快許多。
選擇 DOM 還是選擇 SAX ?
對于需要自己編寫代碼來處理 XML 文檔的開發(fā)人員來說,選擇 DOM 還是 SAX 解析模型是一個(gè)非常重要的設(shè)計(jì)決策。
DOM 采用建立樹形結(jié)構(gòu)的方式訪問 XML 文檔,而 SAX 采用的事件模型。
DOM 解析器把 XML 文檔轉(zhuǎn)化為一個(gè)包含其內(nèi)容的樹,并可以對樹進(jìn)行遍歷。用 DOM 解析模型的優(yōu)點(diǎn)是編程容易,開發(fā)人員只需要調(diào)用建樹的指令,然后利用navigation APIs訪問所需的樹節(jié)點(diǎn)來完成任務(wù)。可以很容易的添加和修改樹中的元素。然而由于使用 DOM 解析器的時(shí)候需要處理整個(gè) XML 文檔,所以對性能和內(nèi)存的要求比較高,尤其是遇到很大的 XML 文件的時(shí)候。由于它的遍歷能力,DOM 解析器常用于 XML 文檔需要頻繁的改變的服務(wù)中。
SAX 解析器采用了基于事件的模型,它在解析 XML 文檔的時(shí)候可以觸發(fā)一系列的事件,當(dāng)發(fā)現(xiàn)給定的tag的時(shí)候,它可以激活一個(gè)回調(diào)方法,告訴該方法制定的標(biāo)簽已經(jīng)找到。SAX 對內(nèi)存的要求通常會(huì)比較低,因?yàn)樗岄_發(fā)人員自己來決定所要處理的tag。特別是當(dāng)開發(fā)人員只需要處理文檔中所包含的部分?jǐn)?shù)據(jù)時(shí),SAX 這種擴(kuò)展能力得到了更好的體現(xiàn)。但用 SAX 解析器的時(shí)候編碼工作會(huì)比較困難,而且很難同時(shí)訪問同一個(gè)文檔中的多處不同數(shù)據(jù)。
Bean文件:
package com.test;
import org.xml.sax.*;
import org.xml.sax.helpers.*;
import javax.xml.parsers.*;
public class MyXMLReader extends DefaultHandler {
java.util.Stack tags = new java.util.Stack();
public MyXMLReader() {
super();
}
public static void main(String args[]) {
long lasting = System.currentTimeMillis();
try {
SAXParserFactory sf = SAXParserFactory.newInstance();
SAXParser sp = sf.newSAXParser();
MyXMLReader reader = new MyXMLReader();
sp.parse(new InputSource("data_10k.xml"), reader);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("運(yùn)行時(shí)間:" + (System.currentTimeMillis() - lasting) + " 毫秒");
}
public void characters(char ch[], int start, int length) throws SAXException {
String tag = (String) tags.peek();
if (tag.equals("NO")) {
System.out.print("車牌號(hào)碼:" + new String(ch, start, length));
}
if (tag.equals("ADDR")) {
System.out.println(" 地址:" + new String(ch, start, length));
}
}
public void startElement(
String uri,
String localName,
String qName,
Attributes attrs) {
tags.push(qName);
}
}
10k消耗時(shí)間:110 47 109 78
100k消耗時(shí)間:344 406 375 422
1000k消耗時(shí)間:3234 3281 3688 3312
10000k消耗時(shí)間:32578 34313 31797 31890 30328
然后是 JDOM http://www.jdom.org/
JDOM 的目的是成為 Java 特定文檔模型,它簡化與 XML 的交互并且比使用 DOM 實(shí)現(xiàn)更快。由于是第一個(gè) Java 特定模型,JDOM 一直得到大力推廣和促進(jìn)。正在考慮通過“Java 規(guī)范請求 JSR-102”將它最終用作“Java 標(biāo)準(zhǔn)擴(kuò)展”。從 2000 年初就已經(jīng)開始了 JDOM 開發(fā)。
JDOM 與 DOM 主要有兩方面不同。首先,JDOM 僅使用具體類而不使用接口。這在某些方面簡化了 API,但是也限制了靈活性。第二,API 大量使用了 Collections 類,簡化了那些已經(jīng)熟悉這些類的 Java 開發(fā)者的使用。
JDOM 文檔聲明其目的是“使用 20%(或更少)的精力解決 80%(或更多)Java/XML 問題”(根據(jù)學(xué)習(xí)曲線假定為 20%)。JDOM 對于大多數(shù) Java/XML 應(yīng)用程序來說當(dāng)然是有用的,并且大多數(shù)開發(fā)者發(fā)現(xiàn) API 比 DOM 容易理解得多。JDOM 還包括對程序行為的相當(dāng)廣泛檢查以防止用戶做任何在 XML 中無意義的事。然而,它仍需要您充分理解 XML 以便做一些超出基本的工作(或者甚至理解某些情況下的錯(cuò)誤)。這也許是比學(xué)習(xí) DOM 或 JDOM 接口都更有意義的工作。
JDOM 自身不包含解析器。它通常使用 SAX2 解析器來解析和驗(yàn)證輸入 XML 文檔(盡管它還可以將以前構(gòu)造的 DOM 表示作為輸入)。它包含一些轉(zhuǎn)換器以將 JDOM 表示輸出成 SAX2 事件流、DOM 模型或 XML 文本文檔。JDOM 是在 Apache 許可證變體下發(fā)布的開放源碼。
Bean文件:
package com.test;
import java.io.*;
import java.util.*;
import org.jdom.*;
import org.jdom.input.*;
public class MyXMLReader {
public static void main(String arge[]) {
long lasting = System.currentTimeMillis();
try {
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(new File("data_10k.xml"));
Element foo = doc.getRootElement();
List allChildren = foo.getChildren();
for(int i=0;i<allChildren.size();i++) {
System.out.print("車牌號(hào)碼:" + ((Element)allChildren.get(i)).getChild("NO").getText());
System.out.println(" 車主地址:" + ((Element)allChildren.get(i)).getChild("ADDR").getText());
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("運(yùn)行時(shí)間:" + (System.currentTimeMillis() - lasting) + " 毫秒");
}
}
10k消耗時(shí)間:125 62 187 94
100k消耗時(shí)間:704 625 640 766
1000k消耗時(shí)間:27984 30750 27859 30656
10000k消耗時(shí)間:OutOfMemoryError
最后是 DOM4J http://dom4j.sourceforge.net/
雖然 DOM4J 代表了完全獨(dú)立的開發(fā)結(jié)果,但最初,它是 JDOM 的一種智能分支。它合并了許多超出基本 XML 文檔表示的功能,包括集成的 XPath 支持、XML Schema 支持以及用于大文檔或流化文檔的基于事件的處理。它還提供了構(gòu)建文檔表示的選項(xiàng),它通過 DOM4J API 和標(biāo)準(zhǔn) DOM 接口具有并行訪問功能。從 2000 下半年開始,它就一直處于開發(fā)之中。
為支持所有這些功能,DOM4J 使用接口和抽象基本類方法。DOM4J 大量使用了 API 中的 Collections 類,但是在許多情況下,它還提供一些替代方法以允許更好的性能或更直接的編碼方法。直接好處是,雖然 DOM4J 付出了更復(fù)雜的 API 的代價(jià),但是它提供了比 JDOM 大得多的靈活性。
在添加靈活性、XPath 集成和對大文檔處理的目標(biāo)時(shí),DOM4J 的目標(biāo)與 JDOM 是一樣的:針對 Java 開發(fā)者的易用性和直觀操作。它還致力于成為比 JDOM 更完整的解決方案,實(shí)現(xiàn)在本質(zhì)上處理所有 Java/XML 問題的目標(biāo)。在完成該目標(biāo)時(shí),它比 JDOM 更少強(qiáng)調(diào)防止不正確的應(yīng)用程序行為。
DOM4J 是一個(gè)非常非常優(yōu)秀的Java XML API,具有性能優(yōu)異、功能強(qiáng)大和極端易用使用的特點(diǎn),同時(shí)它也是一個(gè)開放源代碼的軟件。如今你可以看到越來越多的 Java 軟件都在使用 DOM4J 來讀寫 XML,特別值得一提的是連 Sun 的 JAXM 也在用 DOM4J。
Bean文件:
package com.test;
import java.io.*;
import java.util.*;
import org.dom4j.*;
import org.dom4j.io.*;
public class MyXMLReader {
public static void main(String arge[]) {
long lasting = System.currentTimeMillis();
try {
File f = new File("data_10k.xml");
SAXReader reader = new SAXReader();
Document doc = reader.read(f);
Element root = doc.getRootElement();
Element foo;
for (Iterator i = root.elementIterator("VALUE"); i.hasNext();) {
foo = (Element) i.next();
System.out.print("車牌號(hào)碼:" + foo.elementText("NO"));
System.out.println(" 車主地址:" + foo.elementText("ADDR"));
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("運(yùn)行時(shí)間:" + (System.currentTimeMillis() - lasting) + " 毫秒");
}
}
10k消耗時(shí)間:109 78 109 31
100k消耗時(shí)間:297 359 172 312
1000k消耗時(shí)間:2281 2359 2344 2469
10000k消耗時(shí)間:20938 19922 20031 21078
THE END
JDOM 和 DOM 在性能測試時(shí)表現(xiàn)不佳,在測試 10M 文檔時(shí)內(nèi)存溢出。在小文檔情況下還值得考慮使用 DOM 和 JDOM。雖然 JDOM 的開發(fā)者已經(jīng)說明他們期望在正式發(fā)行版前專注性能問題,但是從性能觀點(diǎn)來看,它確實(shí)沒有值得推薦之處。另外,DOM 仍是一個(gè)非常好的選擇。DOM 實(shí)現(xiàn)廣泛應(yīng)用于多種編程語言。它還是許多其它與 XML 相關(guān)的標(biāo)準(zhǔn)的基礎(chǔ),因?yàn)樗将@得 W3C 推薦(與基于非標(biāo)準(zhǔn)的 Java 模型相對),所以在某些類型的項(xiàng)目中可能也需要它(如在 JavaScript 中使用 DOM)。
SAX表現(xiàn)較好,這要依賴于它特定的解析方式。一個(gè) SAX 檢測即將到來的XML流,但并沒有載入到內(nèi)存(當(dāng)然當(dāng)XML流被讀入時(shí),會(huì)有部分文檔暫時(shí)隱藏在內(nèi)存中)。
無疑,DOM4J是這場測試的獲勝者,目前許多開源項(xiàng)目中大量采用 DOM4J,例如大名鼎鼎的 Hibernate 也用 DOM4J 來讀取 XML 配置文件。如果不考慮可移植性,那就采用DOM4J吧!
參考文獻(xiàn):
http://www-900.ibm.com/developerWorks/cn/xml/x-injava/index.shtml
http://www-900.ibm.com/developerWorks/cn/xml/x-injava2/index.shtml
請注意!引用、轉(zhuǎn)貼本文應(yīng)注明原作者:Rosen Jiang 以及出處:http://www.aygfsteel.com/rosen
在一個(gè)類中,有一個(gè)叫做test()的方法需要被JSP端調(diào)用(test()主要任務(wù)是System.out.print()),于是在test()方法開始的地方加上"long lasting =System.currentTimeMillis(),"在結(jié)束的地方加上"System.out.println("運(yùn)行時(shí)間:"+(System.currentTimeMillis() - lasting)+" 毫秒")"。
然后把test()方法改成main()方法,以便單獨(dú)測試類,JSP端代碼作出相應(yīng)調(diào)整以便訪問main()方法。奇怪的事情發(fā)生了,經(jīng)過反復(fù)測試,使用JSP訪問main()方法消耗的時(shí)間為 451 毫秒,而單獨(dú)運(yùn)行這個(gè)類消耗的時(shí)間為 2864 毫秒。
為什么會(huì)這樣?是不是WEB容器的原因呢?
-----------------------------------------------------------------------------
在一個(gè)人氣很高的論壇上,我得到些解答,自己也總結(jié)了一些,請各位看官來發(fā)表意見:
第一次請求JSP時(shí),WEB容器將JSP發(fā)送到編譯器,編譯成Servlet。然后把Servlet和其他類(比如自己寫的類)緩存在WEB容器中,再放入內(nèi)存常駐,最后將響應(yīng)結(jié)果返回給客戶端;而JSP的所有后繼請求,WEB容器將自動(dòng)載入緩存,除非JSP或者類經(jīng)過修改,否則WEB容器將不會(huì)重新執(zhí)行編譯并構(gòu)造緩存。而單獨(dú)運(yùn)行類就不一樣了,由于沒有WEB容器緩存支持,每次運(yùn)行都需要重新編譯再讀入內(nèi)存才行,所以要慢些了。
另外,根據(jù)測試,在JSP端第一次被調(diào)用的時(shí)候,時(shí)間和單獨(dú)運(yùn)行類差不多,這也印證了上面的解釋吧。
附上源程序
類:
package com.test;
import org.xml.sax.*;
import org.xml.sax.helpers.*;
import javax.xml.parsers.*;
public class MyXMLReader extends DefaultHandler{
java.util.Stack tags=new java.util.Stack();
public MyXMLReader(){
super();
}
public static void main(String args[]){
long lasting =System.currentTimeMillis();
try{
SAXParserFactory sf = SAXParserFactory.newInstance();
SAXParser sp = sf.newSAXParser();
MyXMLReader reader = new MyXMLReader();
sp.parse(new InputSource("data.xml"),reader);
}
catch(Exception e){
e.printStackTrace();
}
System.out.println("運(yùn)行時(shí)間:"+(System.currentTimeMillis() - lasting)+" 毫秒");
}
public void characters (char ch[], int start, int length)
throws SAXException
{
//從棧中得到當(dāng)前節(jié)點(diǎn)的信息
String tag=(String) tags.peek();
if(tag.equals("NO") ){
System.out.print("車牌號(hào)碼:" + new String(ch,start,length));
}
if(tag.equals("ADDR")){
System.out.println(" 地址:" + new String(ch,start,length));
}
}
public void startElement(String uri, String localName, String qName, Attributes attrs){
tags.push(qName);
}
}
JSP:
<%@ page contentType="text/html; charset=gb2312" %>
<%@ page import="com.test.*"%>
<%
long lasting =System.currentTimeMillis();
%>
<html>
<body>
<%
String args[]={""};
MyXMLReader.main(args);
%>
</body>
</html>
請注意!引用、轉(zhuǎn)貼本文應(yīng)注明原作者:Rosen Jiang 以及出處:http://www.aygfsteel.com/rosen
package BMP;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.awt.image.MemoryImageSource;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
public class BMPReader{
??? public String Reader(){?
??????? Image image;??????????????????????????????????? //構(gòu)造一個(gè)目標(biāo)圖
??????? String result="";?????????????????????????????? //返回結(jié)果
?try{
???? FileInputStream fs=new FileInputStream("/test.BMP");
???? int bflen=14;???????????????????????????
???? byte bf[]=new byte[bflen];????????????
???? fs.read(bf,0,bflen);?????????????????????? //讀取14字節(jié)BMP文件頭
???? int bilen=40;?????????????????
???? byte bi[]=new byte[bilen];
???? fs.read(bi,0,bilen);?????????????????????? //讀取40字節(jié)BMP信息頭
???? // 獲取一些重要數(shù)據(jù)
???? int nwidth=(((int)bi[7]&0xff)<<24)???????? //源圖寬度
???? | (((int)bi[6]&0xff)<<16)
???? | (((int)bi[5]&0xff)<<8)
???? | (int)bi[4]&0xff;
???? System.out.println("寬:"+nwidth);
??????????? int nheight=(((int)bi[11]&0xff)<<24)?????? //源圖高度
???? | (((int)bi[10]&0xff)<<16)
???? | (((int)bi[9]&0xff)<<8)
???? | (int)bi[8]&0xff;
???? System.out.println("高:"+nheight);
??????????? //位數(shù)
???? int nbitcount=(((int)bi[15]&0xff)<<8) | (int)bi[14]&0xff;
???? System.out.println("位數(shù):"+nbitcount);
??????????? //源圖大小
???? int nsizeimage=(((int)bi[23]&0xff)<<24)
???? | (((int)bi[22]&0xff)<<16)
???? | (((int)bi[21]&0xff)<<8)
???? | (int)bi[20]&0xff;
???? System.out.println("源圖大小:"+nsizeimage);
??????????? //對24位BMP進(jìn)行解析
???? if(nbitcount==24){
???????? int npad=(nsizeimage/nheight)-nwidth*3;
???????? int ndata[]=new int[nheight*nwidth];
???????? byte brgb[]=new byte[(nwidth+npad)*3*nheight];
???????? fs.read (brgb,0,(nwidth+npad)*3*nheight);
???????? int nindex=0;
???????? for(int j=0;j<nheight;j++){
????? for(int i=0;i<nwidth;i++){
???????????????? ndata [nwidth*(nheight-j-1)+i]=
????????? (255&0xff)<<24
????????? | (((int)brgb[nindex+2]&0xff)<<16)
????????? | (((int)brgb[nindex+1]&0xff)<<8)
????????? | (int)brgb[nindex]&0xff;
???????????????? nindex+=3;
??????????? }
???? nindex+=npad;
??????????????? }
??Toolkit kit=Toolkit.getDefaultToolkit();
??image=kit.createImage(new MemoryImageSource(nwidth,nheight,
????? ndata,0,nwidth));
??????????????? result="從BMP得到圖像image";
??????????????? System.out.println("從BMP得到圖像image");
???? }else{
???????? result="不是24位BMP,失敗!";
??????????????? System.out.println("不是24位BMP,失敗!");
???????? image=(Image)null;
???? }
??????????? fs.close();??????? //關(guān)閉輸入流
???????????
??????????? //開始進(jìn)行圖像壓縮(對image對象進(jìn)行操作)
???? int wideth=image.getWidth(null);?????????????????????????????????? //得到源圖寬
???? int height=image.getHeight(null);????????????????????????????????? //得到源圖長
???? BufferedImage tag=new BufferedImage(wideth/2,height/2,BufferedImage.TYPE_INT_RGB);
???? tag.getGraphics().drawImage(image,0,0,wideth/2,height/2,null);???? //繪制縮小后的圖
???? FileOutputStream out=new FileOutputStream("/newfile.jpg");???????? //輸出到文件流
???? JPEGImageEncoder encoder=JPEGCodec.createJPEGEncoder(out);?????
???? encoder.encode(tag);?????????????????????????????????????????????? //進(jìn)行JPEG編碼
???? out.close();?????? //關(guān)閉輸出流?????????????????????
?}catch (Exception e){
???? System.out.println(e);
??????? }
??????? return result;
??? }
}
??? 相信代碼部分應(yīng)該沒有什么問題吧?通過以下方法,你可以得到更多的信息:
?????? //得到壓縮值
??????? int ncompression = (((int)bi[19])<<24)
??????? | (((int)bi[18])<<16)
??????? | (((int)bi[17])<<8)
??????? | (int)bi[16];
??????? System.out.println("壓縮:"+ncompression);
???????//象素情況
??????? int nxpm = (((int)bi[27]&0xff)<<24)
??????? | (((int)bi[26]&0xff)<<16)
??????? | (((int)bi[25]&0xff)<<8)
??????? | (int)bi[24]&0xff;
??????? System.out.println("X-象素/米:"+nxpm);
??????? int nypm = (((int)bi[31]&0xff)<<24)
??????? | (((int)bi[30]&0xff)<<16)
??????? | (((int)bi[29]&0xff)<<8)
??????? | (int)bi[28]&0xff;
??????? System.out.println("Y-象素/米:"+nypm);
?????? //顏色使用情況
??????? int nclrused = (((int)bi[35]&0xff)<<24)
??????? | (((int)bi[34]&0xff)<<16)
??????? | (((int)bi[33]&0xff)<<8)
??????? | (int)bi[32]&0xff;
??????? System.out.println("顏色使用數(shù):"+nclrused);
??????? int nclrimp = (((int)bi[39]&0xff)<<24)
??????? | (((int)bi[38]&0xff)<<16)
??????? | (((int)bi[37]&0xff)<<8)
??????? | (int)bi[36]&0xff;
??????? System.out.println("顏色顯要:"+nclrimp);
??????? int nplanes = (((int)bi[13]&0xff)<<8) | (int)bi[12]&0xff;
??????? System.out.println("位面:"+nplanes);
???????//信息頭中的圖像大小
??????? int nbisize = (((int)bi[3]&0xff)<<24)?
??????? | (((int)bi[2]&0xff)<<16)
??????? | (((int)bi[1]&0xff)<<8)
??????? | (int)bi[0]&0xff;
??????? System.out.println("BMP信息頭大小:"+nbisize);
?????? //文件大小及種類
??????? int nsize=(((int)bf[5]&0xff)<<24)??????
?????????????? | (((int)bf[4]&0xff)<<16)
??????? | (((int)bf[3]&0xff)<<8)
??????? | (int)bf[2]&0xff;
??????? System.out.println("文件種類:"+(char)bf[0]+(char)bf[1]);
??????? System.out.println("文件大小:"+nsize);
???????
后記
?????? 可以通過變量nbitcount來判斷是否是8位位圖并作出相應(yīng)處理。限于目前24位位圖應(yīng)用較為廣泛,所以沒有寫出相應(yīng)代碼,如有需要可查閱Jeff West與John D.Mitchell之著作《How to read 8- and 24-bit Microsoft Windows bitmaps in Java applications》。
?????? 在此,我謹(jǐn)慎的表示:因?yàn)槲粓D(BMP)沒有經(jīng)過壓縮,所以對于源圖的容量幾乎沒有限制,不會(huì)出現(xiàn)內(nèi)存不足的情況。
???
?????? 在寫這篇文章時(shí)我只進(jìn)行了9M左右BMP的讀取,其實(shí)大家有興趣的話可以利用50M左右的TIF圖轉(zhuǎn)換為BMP(幾乎還是50M)來做試驗(yàn)。并歡迎上來指正。
請注意!引用、轉(zhuǎn)貼本文應(yīng)注明原作者:Rosen Jiang 以及出處:http://www.aygfsteel.com/rosen
通過本文,你將能了解到如何配置服務(wù)以及Google WebService的語法結(jié)構(gòu);怎樣個(gè)性化你的搜索,例如:國家、語言;怎樣提煉搜索結(jié)果。
Google目前已經(jīng)成了Web上最流行的搜索引擎,為了讓諸如new content watchdog、GUI搜索工具和模式分析之類的應(yīng)用程序成為可能,現(xiàn)在它們?yōu)?0億個(gè)頁面建立了索引,開發(fā)者們可以通過基于SOAP的API進(jìn)行調(diào)用。
WebService 簡介
Web應(yīng)用的巨大成功和不斷發(fā)展,使其滲透到商業(yè)領(lǐng)域和個(gè)人生活的各個(gè)方面。人們只要使用瀏覽器,就可以享受到各種各樣的Web服務(wù),例如網(wǎng)上購物,網(wǎng)上交易,網(wǎng)絡(luò)游戲,預(yù)定車票,網(wǎng)上聊天和交友等等。與此同時(shí),由于Web技術(shù)所帶來的優(yōu)勢(統(tǒng)一的客戶端和較好的維護(hù)性),使一些傳統(tǒng)的應(yīng)用紛紛轉(zhuǎn)型到基于B/S架構(gòu)的瘦客戶端應(yīng)用程序,這是因?yàn)樗軌虮苊饣ㄔ谧烂鎽?yīng)用程序發(fā)布上的高成本,也能夠很好的解決客戶和服務(wù)器之間的通信問題。在客戶端和服務(wù)器之間的通信,一個(gè)完美的解決方案是使用HTTP協(xié)議來通信。這是因?yàn)槿魏芜\(yùn)行Web瀏覽器的機(jī)器都使用HTTP協(xié)議,可以很好地透過防火墻進(jìn)行通信。許多商業(yè)程序還面臨另一個(gè)問題,那就是與其他程序的互操作性。目前有很多商業(yè)數(shù)據(jù)仍然在大型主機(jī)上以非關(guān)系文件(VSAM)的形式存放,并由COBOL語言編寫的大型機(jī)程序訪問。而且,還有很多商業(yè)程序使用C++、JAVA、VB和其他各種各樣的語言編寫。現(xiàn)在初了最簡單的程序之外,所有的程序都需要與運(yùn)行在其他異構(gòu)平臺(tái)上的應(yīng)用程序集成并進(jìn)行數(shù)據(jù)交換。在以前,沒有一個(gè)應(yīng)用程序通信標(biāo)準(zhǔn)是獨(dú)立于平臺(tái)、組建模型和編程語言的。只有通過Web Service、客戶端和服務(wù)器才能夠自由的用HTTP進(jìn)行通信,不論兩個(gè)程序的平臺(tái)和編程語言是什么。Web Service技術(shù)完全基于標(biāo)準(zhǔn)的技術(shù),只有基于標(biāo)準(zhǔn),所有的開放廠商才能有相同的標(biāo)準(zhǔn),才能夠在各自的平臺(tái)上開發(fā)出具有跨平臺(tái)互操作能力的軟件產(chǎn)品和解決方案。標(biāo)準(zhǔn)時(shí)達(dá)成跨平臺(tái)互操作能力的靈魂。
Web是為了程序到用戶的交互,而Web Service是為程序到程序的交互做準(zhǔn)備。Web Service使公司可以降低進(jìn)行電子商務(wù)的成本、更快的部署解決方案以及開拓新機(jī)遇。達(dá)到這個(gè)目標(biāo)的關(guān)鍵在于通用的程序到程序通信模型,該模型應(yīng)建立在現(xiàn)有的和新興的標(biāo)準(zhǔn)之上。其中包括:HTTP,SOAP, WSDL, UDDI
SOAP:是“Simple Object Access Protocol”的縮寫,SOAP是消息傳遞的協(xié)議,它規(guī)定了Web Services之間是怎樣傳遞信息的。
簡單的說,SOAP規(guī)定了:
1. 傳遞信息的格式為XML。這就使Web Services能夠在任何平臺(tái)上,用任何語言進(jìn)行實(shí)現(xiàn)。
2. 遠(yuǎn)程對象方法調(diào)用的格式。規(guī)定了怎樣表示被調(diào)用對象以及調(diào)用的方法名稱和參數(shù)類型等。
3. 參數(shù)類型和XML格式之間的映射。這是因?yàn)椋徽{(diào)用的方法有時(shí)候需要傳遞一個(gè)復(fù)雜的參數(shù),例如,一個(gè)Person對象。怎樣用XML來表示一個(gè)對象參數(shù),也是SOAP所定義的范圍。
WSDL:是“Web Services Description Language”的縮寫。WSDL是Web Services的定義語言。當(dāng)實(shí)現(xiàn)了某種服務(wù)的時(shí)候(如:股票查詢服務(wù)),為了讓別的程序調(diào)用,必須告訴大家服務(wù)接口。例如:服務(wù)名稱,服務(wù)所在的機(jī)器名稱,監(jiān)聽端口號(hào),傳遞參數(shù)的類型,個(gè)數(shù)和順序,返回結(jié)果的類型等等。這樣別的應(yīng)用程序才能調(diào)用該服務(wù)。WSDL協(xié)議就是規(guī)定了有關(guān)Web Services描述的標(biāo)準(zhǔn)。
UDDI:是“Universal Description, Discovery,and Integration”的縮寫。簡單說,UDDI用于集中存放和查找WSDL描述文件,起著目錄服務(wù)器的作用。
快速安裝
本文的運(yùn)行環(huán)境是JDK1.3+Tomcat4.0+JSP。要使用Google的服務(wù),必須要有“l(fā)icense key”,可以在https://www.google.com/accounts/NewAccount?continue=http://api.google.com/createkey&followup=http://api.google.com/createkey中取得,輸入相應(yīng)的信息,然后到你的郵箱收取“l(fā)icense key”。接著還需要“Java API for XML Messaging”亦即“JAXM”。它是Java XML Pack的一部分,在http://java.sun.com/xml/downloads/javaxmlpack.html提供。
為了更簡單的表達(dá),我直接用JSP模式,并使用手工編碼,沒有用IDE環(huán)境。
解開剛才下載的java_xml_pack-summer02_01.zip,找到j(luò)ava_xml_pack-summer-02_01\jaxp-1.2_01\xalan.jar文件,用WinRAR解開把org文件夾拷貝到你的應(yīng)用程序的WEB-INF\classes下。找到j(luò)ava_xml_pack-summer-02_01\jaxm-1.1_01\lib\saaj-api.jar文件,解開它并拷貝javax文件夾到同上的目錄。找到j(luò)ava_xml_pack-summer-02_01\jaxm-1.1_01\lib\jaxm-api.jar文件,解開它并拷貝javax文件夾到相同目錄。找到j(luò)ava_xml_pack-summer-02_01\jaxp-1.2_01\jaxp-api.jar文件,解開它并拷貝javax文件夾到相同目錄。找到j(luò)ava_xml_pack-summer-02_01\jaxm-1.1_01\jaxm\saaj-ri.jar文件,解開并拷貝com文件夾到相同目錄。
程序源代碼
<%@ page contentType="text/html;charset=gb2312"%>
<%@ page import="org.apache.xalan.processor.TransformerFactoryImpl"%>
<%@ page import="javax.xml.soap.SOAPConnectionFactory"%>
<%@ page import="javax.xml.soap.SOAPConnection"%>
<%@ page import="javax.xml.soap.MessageFactory"%>
<%@ page import="javax.xml.soap.SOAPMessage"%>
<%@ page import="javax.xml.soap.SOAPPart"%>
<%@ page import="javax.xml.soap.SOAPEnvelope"%>
<%@ page import="javax.xml.soap.SOAPBody"%>
<%@ page import="javax.xml.soap.SOAPElement"%>
<%@ page import="java.io.FileInputStream"%>
<%@ page import="javax.xml.transform.stream.StreamSource"%>
<%@ page import="javax.xml.messaging.URLEndpoint"%>
<%@ page import="javax.xml.transform.TransformerFactory"%>
<%@ page import="javax.xml.transform.Transformer"%>
<%@ page import="javax.xml.transform.Source"%>
<%@ page import="javax.xml.transform.stream.StreamResult"%>
<html>
<head>
<title>google WebService</title>
</head>
<%
try {
//首先建立一個(gè)連接
SOAPConnectionFactory soapConnFactory =
SOAPConnectionFactory.newInstance();
SOAPConnection connection =
soapConnFactory.createConnection();
//接著,創(chuàng)建消息
MessageFactory messageFactory=MessageFactory.newInstance();
SOAPMessage message=messageFactory.createMessage();
//為消息部份創(chuàng)建SOAP對象
SOAPPart soapPart=message.getSOAPPart();
//組裝信息,根據(jù)C盤根目錄下search.msg文件進(jìn)行搜索
StreamSource preppedMsgSrc=new StreamSource(new FileInputStream("/search.msg"));
soapPart.setContent(preppedMsgSrc);
//保存消息
message.saveChanges();
//發(fā)送到目標(biāo)地址
URLEndpoint destination=
new URLEndpoint("http://api.google.com/search/beta2");
//發(fā)送消息
SOAPMessage reply=connection.call(message, destination);
//保存輸出,建立傳出信息
TransformerFactory transformerFactory =
TransformerFactory.newInstance();
//根據(jù)樣式文件translate.xsl進(jìn)行解析
Source styleSheet=new StreamSource("/translate.xsl");
Transformer transformer=
transformerFactory.newTransformer(styleSheet);
//提取收到的內(nèi)容
Source sourceContent=reply.getSOAPPart().getContent();
//建立輸出文件results.out
StreamResult result=new StreamResult("/results.out");
transformer.transform(sourceContent, result);
out.println("文件已生成C:\results.out");
//關(guān)閉連接
connection.close();
}catch(Exception e){
System.out.println(e.getMessage());
}
%>
</body>
</html>
源代碼部分完全按照Google的規(guī)定進(jìn)行編寫,程序注解部分也在其中,這里就不羅嗦了。
搜索格式
<?xml version='1.0' encoding='UTF-8'?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/1999/XMLSchema">
<SOAP-ENV:Body>
<ns1:doGoogleSearch xmlns:ns1="urn:GoogleSearch"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<key xsi:type="xsd:string">00000000000000000000000000000000</key>
<q xsi:type="xsd:string">CSDN論壇</q>
<start xsi:type="xsd:int">0</start>
<maxResults xsi:type="xsd:int">10</maxResults>
<filter xsi:type="xsd:boolean">false</filter>
<restrict xsi:type="xsd:string"></restrict>
<safeSearch xsi:type="xsd:boolean">false</safeSearch>
<lr xsi:type="xsd:string"></lr>
<ie xsi:type="xsd:string">latin1</ie>
<oe xsi:type="xsd:string">latin1</oe>
</ns1:doGoogleSearch>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
search.msg文件標(biāo)簽<<key></key>之前的為固定格式,無需費(fèi)心。標(biāo)簽<key>就是本文第一部分所提到的“l(fā)icense key”,直接復(fù)制過來。標(biāo)簽<q>是指具體要搜索的內(nèi)容。標(biāo)簽<start>是指從第幾個(gè)開始搜索。標(biāo)簽<maxResults>是指每次返回搜索結(jié)果的最大值,Google WebService規(guī)定,最大值只能是“10”。標(biāo)簽<filter>是指過濾掉結(jié)果中相似和域名相同的結(jié)果。標(biāo)簽<restrict>是指國家和主題的約束,例如要限制只在國內(nèi)搜索,就需要輸入countryCN;要限制只在Linux主題內(nèi)搜索,就輸入linux。標(biāo)簽<safeSearch>過濾掉成人信息。標(biāo)簽<lr>搜索的語言,例如只搜索簡體中文,就要輸入lang_zh-CN。標(biāo)簽<ie>和<oe>分別指輸入和輸出的編碼格式默認(rèn)為latin1(UTF-8)。
解析格式
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:apply-templates select="http://item"/>
</xsl:template>
<xsl:template match="item">
<xsl:value-of select="title" disable-output-escaping="yes"/>
<xsl:text>
</xsl:text>
<xsl:value-of select="URL"/>
<xsl:text>
</xsl:text>
<xsl:value-of select="summary"/>
</xsl:template>
</xsl:stylesheet>
translate.xsl文件。我們從<xsl:value-of select="title" disable-output-escaping="yes"/>這一句開始,select="title"確定了返回結(jié)果的第一部分為標(biāo)題。接下來,select="URL"解析出URL地址。<xsl:text></xsl:text>暫且理解為換行標(biāo)簽吧。select="summary"解析出摘要。還有一些標(biāo)簽,詳情請參考“Google Web APIs Reference”。
后 記
程序運(yùn)行以后所產(chǎn)生的結(jié)果results.out請大家自己去查看,在這里就不一一列舉了。
創(chuàng)作這篇文章的目的純屬個(gè)人愛好,完全是對Google引擎的一種喜愛。文章不是很有深度,希望能給各位起到拋磚引玉的作用我就滿足了,更加豐富的功能還有待我們?nèi)ヌ剿鳎?BR>
請注意!引用、轉(zhuǎn)貼本文應(yīng)注明原作者:Rosen Jiang 以及出處:http://www.aygfsteel.com/rosen