在Unix/Linux上令(java)JVM支持中文输出
?在Unix/Linux上令(java)JVM支持中文輸出
一、在Unix/Linux上令JVM支持中文輸出
如 果用戶使用的是UNIX的遠(yuǎn)程服務(wù)器,就會遇到中文字體在圖像中輸出的問題,特別是由于許多管理員并不喜歡把主機(jī)的locale定為zh(因為意味著可能 出亂碼或必須裝微形圖形終端象zhcon,但很多情況下這樣的條件并不具備)。大部分程序員的JAVA經(jīng)驗茍限于JSP腳本程序,部分熟練的程序員大概開 發(fā)過中間件、servlet、applet或在WINDOWS上運(yùn)行的GUI程序。如果開發(fā)的jfreechart是使用WINDOWS作為主機(jī)運(yùn)行的 話,可以略過這一段,但如果使用的是UNIX類型的服務(wù)器的話,就常常遇到意想不到的中文顯示困難,甚至還未到輸出中文字體的階段,程序就報告 display異常錯誤。原因就在于,JAVA awt原來是針對(X)windows GUI編寫的程序,它常常需要使用display 1:0的設(shè)置設(shè)定顯示方式,在服務(wù)器模式下(象jsp或servlet),根本就不會有XWindowns運(yùn)行,這時就會在許多程序中引起can not got display setting to 0:0的錯誤,包括jfreechart。解決辦法是在JVM啟動中增加-Djava.awt.headless=true的設(shè)置。但這樣又帶來另一個問 題,會令使用象frame.getImage()方法的代碼中引起headless? Exception,導(dǎo)致程序中止,而使用ImageBuffer的程序就不會受到影響。
象jfreechart這樣基于java awt,java Swing, java 2D API和程序應(yīng)用到Linux/UNIX上,中文字體的輸出是一個必須解決的問題,否則連jfreereport都不能使用了。servlet也會碰到類 似的問題,但解決方式顯得相對簡單,servlet package已經(jīng)內(nèi)置了解決辦法,一般情況下,在 servlet抬頭設(shè)兩句:
response.setContentType("text/html;charset=UTF-8");
request.setCharacterEncoding("UTF-8");??
中 文亂碼就不得存在。與簡單的jsp/servlet字符集轉(zhuǎn)換相比,這個問題要復(fù)雜得多,甚至比一般的linux中文化還要復(fù)雜。在正常情況下, jre只包含少數(shù)幾種字體(Font),但可以從X 系統(tǒng),象windows獲得喜歡的字體支持;因此,如果開發(fā)者和使用者是在中文WINDOWS系統(tǒng)上開發(fā),大概不會發(fā)覺問題的存在。但一旦當(dāng)程序發(fā)布到 UNIX/Linux系統(tǒng)上后,就會發(fā)現(xiàn)圖形中的中文字符成為一個個的問號或者小方框。而此時,象jsp/servlet這樣的程序在客戶端的顯示卻是完 全正常的。一般情況下,JAVA默認(rèn)情況下是使用en_OTF-8,或者ISO_8859_1讀入字符串,因此,象JSP通常使用從8859_1強(qiáng)制轉(zhuǎn)型 為gb3312/GBK,就可以正常顯示中文,但是在上述的情形下,這種強(qiáng)制轉(zhuǎn)型地是完全無效的。為什么呢?如果程序員的系統(tǒng)概念是清晰的話,就會明白, JSP/SERVLET的字符串輸出,只是輸出字型,然后由客戶端(一般是瀏覽器)在客戶端桌面重整字型,用的是客戶端的字體,而相反,JfreeChart這樣的圖形程序輸出的是一個圖像,用的是服務(wù)器端jre的字體,與Xwindows的字體也無關(guān)。當(dāng)系統(tǒng)本身不帶有字型時(font),這正是服務(wù)器所常見的,就只能向jre添加支持中文的字體(font)才能根本上解決這個問題。
Jre 的字體設(shè)置原理與Xwindows相似,并延用相同的工具,事實上,二進(jìn)制字體文件延用相同的標(biāo)準(zhǔn),各個公司間的字體集,象聯(lián)想、方正、微軟以及 linux Xwindows下是相同的,完全可以互相拷貝,僅僅是讀取字體的方式流程和設(shè)置方式稍有區(qū)別。目錄提及l(fā)inux漢化的文章,其中主要就是增加中文字體 的支持,很多是廢話連篇,不知其所以然亂撞一通后驚呼"搞定啦"這樣不可重復(fù)的形式。所以這里先復(fù)習(xí)一下,然后和JRE的設(shè)置對照,原理就會顯得比較清 晰。目前l(fā)inux的字體有兩處使用,一是linux console下的字體,二是Xwin等應(yīng)用程序的字體,包括象zhcon這樣的偽console程序。每處應(yīng)用字體的程序都可以有自已的字體設(shè)置目錄; 但隨著Linux集成程度的強(qiáng)化,都傾向向通過默認(rèn)的unixsocket7000端口調(diào)用xfs的字體服務(wù)。因此,字體設(shè)置只需對xfs進(jìn)行設(shè)置就可以 完成。一些文章聲稱要停掉XFS,實際上毫無必要;xfs的調(diào)用僅僅是作為一個在XFConfig中的FontPath選項,作為另一個添加字體的方法, 就是直接把包含字體的目錄添加到FontPath,然后手工執(zhí)行ttmkfdir——恰恰這本來是xfs設(shè)計代替您去做的。用戶實際上需要做的,要么是直 接在圖形工具中把字體文件添加到fonts:\\\中,或者是手工把字體文件加到xfs的目錄下的對應(yīng)locale的目錄中,一般是在 /usr/share/lib/fonts/zh_CN/TrueType,重啟xfs就搞定了。作為手工添加到XFConfig中的目錄,在XWin 中,簡單地說,字體位圖文件是通用的,包括對JRE,放在某一個目錄中,用戶需要做的就是通知XWIN這些目錄在什么地方,設(shè)置的位置就在 /etc/X11/XConfig的FontPath項。運(yùn)行ttmkfdir命令生成fonts.dir文件,實際上都是字體調(diào)用的對照表,另外用戶可 以編輯fonts.alias這樣的文件,目的就是讓字體有個易記的名字。因此,字體的安裝關(guān)鍵在于字體位圖文件(拷到某個目錄),對照文件(由 ttmkfdir命令生成),和字體別名設(shè)置,所不同的是,在Xwin中這些由xfs自動完成,在jre中,就要開發(fā)者自已手工完成。
就Jre 而言,字體位圖目錄是固定的,在$JRE_HOME/lib/fonts目錄中;fonts.dir*的目錄對照表文件也是一樣的,同樣是由 ttmkdir程序生成,而相當(dāng)于別名等設(shè)置的文件,集中在$JRE_HOME/lib目錄下的*font.properties*"文件中定義。如果 JVM能直接支持中文輸出,那么就要求*font.properties*屬性文件中指示的字體型本身是支持中文的(換言之,JSDK自帶的字體文件是不 支持中文的)。按http://java.sun.com/j2se/1.3/docs/guide/intl/fontprop.html的說明,JVM按以下順序搜索字體屬性文件,尖括號是JVM檢測的系統(tǒng)屬性:
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
但 在大多數(shù)情況下,實際上只需要面向一個font.properties文件。重新編一個font.properties文件是一項艱苦的工程,幸好在 Linux中有一個font.properties.zh.Turbo,本來是面向TurboLinux用戶,不過在大多數(shù)情況下可以基于它修改。把這個 文件重命名為font.properties,覆蓋掉原來的文件,但系統(tǒng)這時仍不支持中文,查看一下,就會發(fā)現(xiàn) font.properties.zh.Turbo文件中的"-tlc-song-medium-r-normal--*-%d-*-*-c-*-gbk -0"字型在fonts.dir對照表中并不具備,這種字型包含在TurboLinux的系統(tǒng)字型庫中。下面的方法有兩個,一是安裝這種字體,二是更改另 一種字體型庫并重新指定。TurboLinux的字體安裝文件名字是ttf-zh-song*rpm,在互聯(lián)網(wǎng)上可以找到,安裝后把 /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下找到一兩個支持中文的字體文件。
把 這些文件統(tǒng)統(tǒng)拷到JRE的fonts目錄并不能令JVM立刻支持中文,回想一下前面提到的,在font.properties中指定的文字類型,必須有一 個對照表fonts.dir指示JVM如何把用戶調(diào)用的font類型匹配到相應(yīng)的字型文件上。因此,運(yùn)行ttmkfdir > fonts.dir生成新的對照表。用Vi打開這個文件,最上面的數(shù)字是系統(tǒng)可以調(diào)用的字型數(shù)目,下面的屬性值對左側(cè)就是物理字型名稱,右側(cè)是它的編號, 這就是用到font.properties 文件中指明使用的編號(包含了設(shè)置,左側(cè)的就是字符的別名,即虛擬字型),區(qū)別僅僅是把0-0-0c-0這類設(shè)置中的某幾項改作通配符和%d接受調(diào)用參數(shù) 而已,不改也行,大不了輸出的字難看一點(反正我不是美工,不太關(guān)心)。用可用的字型編號代替了font.properties中無效的字型設(shè)置后,理論 上似乎JVM已經(jīng)支持中文了,但在實際操作上,仍是經(jīng)常見到問號、空格之類,原因就在于JAVA對中文的支持不但與運(yùn)行環(huán)境有關(guān),還與編譯參數(shù)有關(guān),如果 類文件不是以gb2312/encoding編譯的話,等同于讀入是OTF-8/8859_1,這時再轉(zhuǎn)換也沒有用了,因此,如果是drawString 之類的,必須切記使用(-encoding gb2312);當(dāng)然,如果操作系統(tǒng)本身已經(jīng)是中文的話,這條就由編譯器自動采納了。
作者Blog:http://blog.csdn.net/zwwwxy/
轉(zhuǎn)載于:https://www.cnblogs.com/swordzj/archive/2005/04/24/2034790.html
《新程序員》:云原生和全面數(shù)字化實踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的在Unix/Linux上令(java)JVM支持中文输出的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 用Flash MX 2004自制调色版和
- 下一篇: 系统分析员考试要略