java Swing程序在linux下的乱码问题

Linux下Java程序界面中中文显示的问题,经常存在于XWindow配置、Java程序内部错误和Java环境配置等几个方面。为了辅助进行错误定位,我们可以写一个简单的Swing程序,如下所示: 

//在JDK 1.3.1 下调试运行通过(Linux & Windows 平台) 
import javax.swing.*;          
import java.awt.*; 
import java.awt.event.*; 
public class HZSwingTest { 
    //Define two strings that containing DBCS and English character. 
    private static String DBCSValue = "This is a DBCS string[汉字]"; 
    private static String DBCSWindowTitle = "DBCS Title[汉字]"; 
    public Component createComponents() { 
        final JLabel label = new JLabel(DBCSValue); 
        JPanel pane = new JPanel(); 
        pane.setBorder(BorderFactory.createEmptyBorder(30, 30, 10, 30)); 
        pane.setLayout(new GridLayout(0, 1)); 
        pane.add(label); 
        return pane; 
    } 
    public static void main(String[] args) { 
        try { 
            UIManager.setLookAndFeel( 
                UIManager.getCrossPlatformLookAndFeelClassName());        } catch (Exception e) { } 
        //Create the top-level container and add contents to it. 
        JFrame frame = new JFrame(DBCSWindowTitle); 
        HZSwingTest app = new HZSwingTest(); 
        Component contents = app.createComponents(); 
        frame.getContentPane().add(contents, BorderLayout.CENTER); 
        //Finish setting up the frame, and show it. 
        frame.addWindowListener(new WindowAdapter() { 
            public void windowClosing(WindowEvent e) { 
                System.exit(0); 
            } 
        }); 
        frame.pack(); 
        frame.setVisible(true); 
    } 

                 


该程序简单模拟了WAS出错时的界面,创建一个标题为中文字符串的窗口,其中还包含一个显示中文字符串的标签。在Windows 2000 中文版和United Linux 1.0平台上,其运行结果如下所示: 


图 3 United Linux 1.0运行结果 


图 4 Windows 2000中文版运行结果 


由于Windows平台下程序运行正常,说明该测试程序在汉字显示代码上的编写没有问题。而该测试程序在United Linux 1.0上的错误现象,跟图1、2一致,因此错误可能在XWindow配置和Java环境配置上。 

而在Java虚机实现时,Java程序窗口的生成是通过调用操作系统API来完成的,跟具体操作系统相关。因此,同样的Java程序窗口在不同操作系统上,其标题栏按钮、标题栏显示风格、边框风格各不相同。而对于具体的Java窗口内部Swing和AWT控件,其生成和显示是由Java虚机本身来完成的,跟具体操作系统无关。由于图1、2、3中Java窗口标题栏部分中文显示正常,表明XWindow已经能够支持中文的显示,可以初步排除XWindow配置的问题。因此,下边的分析主要针对Java环境字体配置进行。 

在Java平台中,字体配置信息主要定义于font.properties系列文件中,存放于JRE/lib目录下。其中定义了五种平台无关的逻辑字体:Serif, SansSerif, Monospaced, Dialog和DialogInput,每一个JVM的实现,都必须包含这五种字体。另外,还定义了逻辑字体跟实际字体的映射等信息。为了支持不同的操作系统版本和Locale,font.properties包含了附带不同后缀的多个版本。 

从Sun的文档"Adding Fonts to the Java Runtime"[参见参考文献1]中,我们可以得知: 在英文环境下,字体属性由无后缀的font.properties 定义。为了一些操作系统的特殊问题,字体属性文件的名字可以加入操作系统的版本号作为后缀。例如,Solaris 2.5.1 不支持 TrueType 字体,所以字体属性文件font.properties.5.5.1 将只包含 F3 字体。在大多数操作系统中,版本后缀的值由System.getProperty("os.version")来确定。 

如果环境是日文、韩文、简体中文或繁体中文,就必须使用相应于特定环境的 font.properties 文件。这些文件可以通过文件名后边加上相应的国家或者locale后缀识别,格式为font.properties.<locale>。该<locale>实际上由<language>_<region>_<encoding>三部分构成。而<language>、<region>和<encoding>分别对应了系统属性(由System.getProperty方法返回的字符串)"user.language"、"user.region"和"file.encoding"。而这个font.properties.<locale>名也可以跟操作系统的版本结合使用。 

概括的讲,Java按照以下顺序搜索字体属性文件: 

Java代码   收藏代码
  1. font.properties.<language>_<region>_<encoding>.<osVersion>  
  2. font.properties.<language>_<region>_<encoding>  
  3. font.properties.<language>_<region>.<osVersion>  
  4. font.properties.<language>_<region>  
  5. font.properties.<language>_<encoding>.<osVersion>  
  6. font.properties.<language>_<encoding>  
  7. font.properties.<language>_<osVersion>  
  8. font.properties.<language>  
  9. font.properties.<encoding>.<osVersion>  
  10. font.properties.<encoding>  
  11. font.properties.<osVersion>  
  12. font.properties  

为了确定United Linux下使用的字体属性文件,我们写了以下的程序: 

Java代码   收藏代码
  1. public class PrintLocale {  
  2.     public static void main(String[] args) {  
  3.         System.out.println(System.getProperty("user.language"));  
  4.         System.out.println(System.getProperty("user.region"));  
  5.         System.out.println(System.getProperty("file.encoding"));  
  6.         System.out.println(System.getProperty("os.version"));  
  7.     }  
  8. }  

其执行过程及结果如下所示: 

linux:/opt/WebSphere/AppServer/java/bin # ./java PrintLocale 
zh 
CN 
GB2312 
2.4.19-4GB 
linux:/opt/WebSphere/AppServer/java/bin # 
                 


通过该执行结果、以及与JRE/lib目录下的Java字体属性文件名的比较,我们可以确定,在United Linux 1.0中文环境下,选用的字体文件是font.properties.zh。 

经过对font.properties.zh的检查,我们可以发现以下几行: 

filename.song_medium_r=gkai00mp.ttf 
filename.song_medium_i=gkai00mp.ttf 
filename.song_bold_r=gkai00mp.ttf 
filename.song_bold_i=gkai00mp.ttf 
filename.fangsong_medium_r=gkai00mp.ttf 
filename.fangsong_medium_i=gkai00mp.ttf 
filename.fangsong_bold_r=gkai00mp.ttf 
filename.fangsong_bold_i=gkai00mp.ttf 
filename.kai_medium_r=gkai00mp.ttf 
                 


它主要用来指定逻辑字体名跟实际物理字体名之间的映射。而所指定的物理字体gkai00mp.ttf在WAS安装目录/java/jre/lib/fonts并不存在。 

这就是问题的根源! 


第三部分:问题解决  


经过以上的分析,我们可以得知中文字符显示错误,是因为font.properties.zh中指定的字体丢失引起的。两种可能的修改方法如下: 

方法一: 

将一个符合要求的TTF字体文件拷贝到jre/lib/fonts目录下,改名成gkai00mp.ttf即可。 

例如,在United Linux 1.0下,可以做以下操作: 

cd /usr/lib/X11/fonts/truetype/ 
cp hya6gb3.ttf /opt/WebSphere/AppServer/java/jre/lib/fonts 
cd /opt/WebSphere/AppServer/java/jre/lib/fonts 
mv hya6gb3.ttf gkai00mp.ttf 
                 


方法二: 

打开 font.properties.zh,将对gkai00mp.ttf的引用替换成对操作系统中实际存在的字体引用,并且在font.properties.zh中加上该字体的路径,做法如下: 

(1) 打开font.properties.zh 

(2) 将"gkai00mp.ttf"全文替换成"hya6gb3.ttf"(共九处) 

(3) 在该文件末尾加上一行:appendedfontpath=/usr/lib/X11/fonts/truetype 

以上只修改了WAS安装目录下Java子目录中的虚机,解决了WAS的一些工具界面上的乱码问题。而对于安装和卸载界面上的乱码,修改方法相同,只是对应虚机路径有所改变,分别是"安装程序根目录/jdk"和"WAS安装目录/_uninst/_jvm" 

字库就是字型库(FONT LIBRARY),其实计算机上显示的每个字符(不管它是哪种语言的),都是一个小的图案。字库就是把这些小的图案以图片的某种形式保存起来,需要显示的时候还原出来就可以了。在WINDOWS操作系统里的字库存放在系统盘windows\fonts文件夹下,在linux操作系统中字库存放在这/usr/share/fonts/文件夹下。 

3  Java语言中产生乱码的原因及解决方法 

3.1基于awt(swing)的图形界面程序中文显示乱码 

基于awt(swing)的图形界面程序中,一般会出现菜单中的中文显示乱码,其原因一般是JVM找不到用来显示中文的字库,JVM在原始的安装下是没有中文字库的,而linux的发行版本又各不相同,其字库存放的路径和名字又各不相同,所以JVM一般是找不到linux操作系统内带的字库,解决方法是让JVM能找到linux操作系统内带的字库,如在Redflag 6.0下可以通过下面命令解决: 

mkdir /usr/java/jdk1.6.0/jre/lib/fonts/fallback 

ln -s /usr/share/fonts/chinese/TrueType/*.ttf /usr/java/jdk1.6.0/jre/lib/fonts/fallback 

一般不需要修改JRE/lib/目录下的字体配置文件(fontconfig.OS.Version.properties)。 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值