在Unix/Linux上令(java)JVM支援中文輸出

來源:互聯網
上載者:User
unix|中文
原文: 在Unix/Linux上令(java)JVM支援中文輸出

一、在Unix/Linux上令JVM支援中文輸出

如果使用者使用的是UNIX的遠程伺服器,就會遇到中文字型在映像中輸出的問題,特別是由於許多管理員並不喜歡把主機的locale定為zh(因為意味著可能出亂碼或必須裝微形圖形終端象zhcon,但很多情況下這樣的條件並不具備)。大部分程式員的JAVA經驗苟限於JSP指令碼程式,部分熟練的程式員大概開發過中介軟體、servlet、applet或在WINDOWS上啟動並執行GUI程式。如果開發的jfreechart是使用WINDOWS作為主機啟動並執行話,可以略過這一段,但如果使用的是UNIX類型的伺服器的話,就常常遇到意想不到的中文顯示困難,甚至還未到輸出中文字型的階段,程式就報告 display異常錯誤。原因就在於,JAVA awt原來是針對(X)windows GUI編寫的程式,它常常需要使用display 1:0的設定設定顯示方式,在伺服器模式下(象jsp或servlet),根本就不會有XWindowns運行,這時就會在許多程式中引起can not got display setting to 0:0的錯誤,包括jfreechart。解決辦法是在JVM啟動中增加-Djava.awt.headless=true的設定。但這樣又帶來另一個問題,會令使用象frame.getImage()方法的代碼中引起headless  Exception,導致程式中止,而使用ImageBuffer的程式就不會受到影響。

象jfreechart這樣基於java awt,java Swing, java 2D API和程式應用到Linux/UNIX上,中文字型的輸出是一個必須解決的問題,否則連jfreereport都不能使用了。servlet也會碰到類似的問題,但解決方式顯得相對簡單,servlet package已經內建瞭解決辦法,一般情況下,在 servlet抬頭設兩句:

response.setContentType("text/html;charset=UTF-8");request.setCharacterEncoding("UTF-8");  

中文亂碼就不得存在。與簡單的jsp/servlet字元集轉換相比,這個問題要複雜得多,甚至比一般的linux中文化還要複雜。在正常情況下, jre只包含少數幾種字型(Font),但可以從X 系統,象windows獲得喜歡的字型支援;因此,如果開發人員和使用者是在中文WINDOWS系統上開發,大概不會發覺問題的存在。但一旦當程式發布到 UNIX/Linux系統上後,就會發現圖形中的中文字元成為一個個的問號或者小方框。而此時,象jsp/servlet這樣的程式在用戶端的顯示卻是完全正常的。一般情況下,JAVA預設情況下是使用en_OTF-8,或者ISO_8859_1讀入字串,因此,象JSP通常使用從8859_1強制轉型為gb3312/GBK,就可以正常顯示中文,但是在上述的情形下,這種強制轉型地是完全無效的。為什麼呢?如果程式員的系統概念是清晰的話,就會明白, JSP/SERVLET的字串輸出,只是輸出字型,然後由用戶端(一般是瀏覽器)在用戶端案頭重整字型,用的是用戶端的字型,而相反,JfreeChart這樣的圖形程式輸出的是一個映像,用的是伺服器端jre的字型,與Xwindows的字型也無關。當系統本身不帶有字型時(font),這正是伺服器所常見的,就只能向jre添加支援中文的字型(font)才能根本上解決這個問題。

Jre 的字型設定原理與Xwindows相似,並延用相同的工具,事實上,二進位字型檔延用相同的標準,各個公司間的字型集,象聯想、方正、微軟以及 linux Xwindows下是相同的,完全可以互相拷貝,僅僅是讀取字型的方式流程和設定方式稍有區別。目錄提及linux漢化的文章,其中主要就是增加中文字型的支援,很多是廢話連篇,不知其所以然亂撞一通後驚呼"搞定啦"這樣不可重複的形式。所以這裡先複習一下,然後和JRE的設定對照,原理就會顯得比較清晰。目前linux的字型有兩處使用,一是linux console下的字型,二是Xwin等應用程式的字型,包括象zhcon這樣的偽console程式。每處應用字型的程式都可以有自已的字型設定目錄;但隨著Linux整合程度的強化,都傾向向通過預設的unixsocket7000連接埠調用xfs的字型服務。因此,字型設定只需對xfs進行設定就可以完成。一些文章聲稱要停掉XFS,實際上毫無必要;xfs的調用僅僅是作為一個在XFConfig中的FontPath選項,作為另一個添加字型的方法,就是直接把包含字型的目錄添加到FontPath,然後手工執行ttmkfdir——恰恰這本來是xfs設計代替您去做的。使用者實際上需要做的,要麼是直接在圖形工具中把字型檔添加到fonts:\\\中,或者是手工把字型檔加到xfs的目錄下的對應locale的目錄中,一般是在 /usr/share/lib/fonts/zh_CN/TrueType,重啟xfs就搞定了。作為手工添加到XFConfig中的目錄,在XWin 中,簡單地說,字型位元影像檔案是通用的,包括對JRE,放在某一個目錄中,使用者需要做的就是通知XWIN這些目錄在什麼地方,設定的位置就在 /etc/X11/XConfig的FontPath項。運行ttmkfdir命令產生fonts.dir檔案,實際上都是字型調用的對照表,另外使用者可以編輯fonts.alias這樣的檔案,目的就是讓字型有個易記的名字。因此,字型的安裝關鍵在於字型位元影像檔案(拷到某個目錄),對照檔案(由 ttmkfdir命令產生),和字型別名設定,所不同的是,在Xwin中這些由xfs自動完成,在jre中,就要開發人員自已手工完成。

就Jre 而言,字型位元影像目錄是固定的,在$JRE_HOME/lib/fonts目錄中;fonts.dir*的目錄對照表檔案也是一樣的,同樣是由 ttmkdir程式產生,而相當於別名等設定的檔案,集中在$JRE_HOME/lib目錄下的*font.properties*"檔案中定義。如果 JVM能直接支援中文輸出,那麼就要求*font.properties*屬性檔案中指示的字型型本身是支援中文的(換言之,JSDK內建的字型檔是不支援中文的)。按http://java.sun.com/j2se/1.3/docs/guide/intl/fontprop.html的說明,JVM按以下順序搜尋字型屬性檔案,角括弧是JVM檢測的系統屬性:

font.properties.<language>_<region>_<encoding>.<osVersion>font.properties.<language>_<region>_<encoding>font.properties.<language>_<region>.<osVersion>font.properties.<language>_<region>font.properties.<language>_<encoding>.<osVersion>font.properties.<language>_<encoding>font.properties.<language>_<osVersion>font.properties.<language>font.properties.<encoding>.<osVersion>font.properties.<encoding>font.properties.<osVersion>font.properties

但在大多數情況下,實際上只需要面向一個font.properties檔案。重新編一個font.properties檔案是一項艱苦的工程,幸好在 Linux中有一個font.properties.zh.Turbo,本來是面向TurboLinux使用者,不過在大多數情況下可以基於它修改。把這個檔案重新命名為font.properties,覆蓋掉原來的檔案,但系統這時仍不支援中文,查看一下,就會發現 font.properties.zh.Turbo檔案中的"-tlc-song-medium-r-normal--*-%d-*-*-c-*-gbk -0"字型在fonts.dir對照表中並不具備,這種字型包含在TurboLinux的系統字型庫中。下面的方法有兩個,一是安裝這種字型,二是更改另一種字型型庫並重新指定。TurboLinux的字型安裝檔案名稱字是ttf-zh-song*rpm,在互連網上可以找到,安裝後把 /usr/lib/X11/fonts/tt下的ttf檔案拷貝到$JRE_HOME/lib/fonts目錄下,重建fonts.dir檔案。第二種辦法就是重找字型庫,微軟WINDOWS上的fonts目錄下的ttf檔案一般可用,但更全的是從http://www.microsoft.com/china/windows2000/downloads/18030.asp 下載它的字元集檔案,安裝後把ttf拷到JRE的fonts目錄下;另外, XWin如果支援中文的話,可以從/usr/lib/X11/fonts/TrueType下找到一兩個支援中文的字型檔。

把這些檔案統統拷到JRE的fonts目錄並不能令JVM立刻支援中文,回想一下前面提到的,在font.properties中指定的文字類型,必須有一個對照表fonts.dir指示JVM如何把使用者調用的font類型匹配到相應的字型檔案上。因此,運行ttmkfdir > fonts.dir產生新的對照表。用Vi開啟這個檔案,最上面的數字是系統可以調用的字型數目,下面的屬性值對左側就是物理字型名稱,右側是它的編號,這就是用到font.properties 檔案中指明使用的編號(包含了設定,左側的就是字元的別名,即虛擬字型),區別僅僅是把0-0-0c-0這類設定中的某幾項改作萬用字元和%d接受調用參數而已,不改也行,大不了輸出的字難看一點(反正我不是美工,不太關心)。用可用的字型編號代替了font.properties中無效的字型設定後,理論上似乎JVM已經支援中文了,但在實際操作上,仍是經常見到問號、空格之類,原因就在於JAVA對中文的支援不但與運行環境有關,還與編譯參數有關,如果類檔案不是以gb2312/encoding編譯的話,等同於讀入是OTF-8/8859_1,這時再轉換也沒有用了,因此,如果是drawString 之類的,必須切記使用(-encoding gb2312);當然,如果作業系統本身已經是中文的話,這條就由編譯器自動採納了。


相關文章

Cloud Intelligence Leading the Digital Future

Alibaba Cloud ACtivate Online Conference, Nov. 20th & 21st, 2019 (UTC+08)

Register Now >

Starter Package

SSD Cloud server and data transfer for only $2.50 a month

Get Started >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。