搜尋
首頁運維linux運維如何解決java linux檔中文亂碼問題

java linux檔案中文亂碼的解決方法:1、下載jdk1.8的sun原始碼;2、將Font的創建從實體字體改為邏輯字體;3、重啟服務即可。

如何解決java linux檔中文亂碼問題

本文操作環境:linux5.9.8系統,jdk1.8,Dell G3電腦。

如何解決java linux檔案中文亂碼問題?

#Linux環境下Java中文亂碼解決方案

相信很多朋友遇到過Java的亂碼問題,最近我也在解決一個「使用文字產生圖片過程中中文以及特殊字元亂碼」的問題;花了我大量時間,Debug了sun.font、sun.awt下面的各種原始碼,終於搞懂了其機制,解決了目前次問題;現在把問題解決過程給寫下來,做個記錄,以免以後再次遇到。

遇到的問題

下面是我想要執行的程式碼(經過極度簡化,但意思沒變):

public static void main(String[] args) throws IOException {
   File file = new File("test.png");
   Font font = new Font("宋体", Font.PLAIN, 10);
   BufferedImage bi = new BufferedImage(400, 200, BufferedImage.TYPE_INT_ARGB);
   Graphics2D g2 = (Graphics2D) bi.getGraphics();
   g2.setBackground(Color.WHITE);
   g2.clearRect(0, 0, 400, 200);
   g2.setFont(font);
   g2.setColor(Color.BLACK);
   g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
   g2.drawString("为什么没有(ꐚꌒꑿꆺ)(ꐚꌒꑿꆺ)这名字特殊不?@¥¥¥ 为什么没有(ꐚꌒꑿꆺ)(ꐚꌒꑿꆺ)这名字特 ", 0, 10);
   g2.dispose();
   ImageIO.write(bi, PNG, file);
}

目標當然是想在開啟test. png的時候看到如下場景:

 

在本地調試沒問題之後,就放到了測試機(Linux)上面去執行了,執行結果簡直撲街:

 

jdk1.8的sun源碼下載

奉行程式設計師一貫作風:既然有問題,那就Debug!
坑爹的是現在的原始碼包已經不包含sun包的程式碼了!
幸好java官方確認OpenJDK的程式碼基本上和JVM源碼一致,可以直接從OpenJDK8u進行下載:jdk8u

至於如何使用源碼debug,這個就不寫了··· 這都不會基本也就別看這文章了

定位問題

直接下載好源碼,遠端斷點,伺服器執行,在debug中先發現了第一個產生本地和測試伺服器不一致的程式碼:

 原來JVM建立Font的時候會使用FontManagerFactory取得FontManager,而不同的系統所使用的FontManager是不同的! Mac用的是CFontManager,Linux用的是X11FontManager!

那麼這兩個FontManager的不同會導致什麼不同呢?

CFontManager會建立CFont作為Font2D,這個CFont是JVM專門為mac創建的類,看類別和方法的註解可以知道在mac環境下有時候物理字體會被CFont包裝,而這是在native程式碼中完成的:

X11FontManager所建立的Font2D是包含了邏輯字體和實體字體的集合。 X11FontManager繼承了FcFontManager,FcFontManager繼承了SunFontManager;我們來看看X11FontManager的loadFonts()方法,直接使用了SunFontManager的loadFonts(),SunFontManager的loadFonts()方法載入了物理字體,SunFontManager實作了FontManager的preferLocaleFonts()方法,載入了邏輯字體:

#邏輯字體與物理字體

代碼debug到這邊基本上已經確認了是不同環境的字體載入問題,那麼在debug linux環境的時候發現的邏輯字體和實體字體是什麼東西呢?

實體字型

實體字型是實際的字型庫,包含字形資料和資料表,這些資料和資料表使用字型技術(如TrueType 或PostScript Type 1)將字元序列對應到字形序列。 Java Platform 的所有實作都支援 TrueType 字型;對其他字型技術的支援是與實作相關的。實體字體可以使用字體名稱,如 Helvetica、Palatino、HonMincho 或任意數量的其他字體名稱。通常,每種物理字體只支援有限的書寫系統集合,例如,只支援拉丁文字符,或只支援日文和基本拉丁文。可用的實體字體集合隨配置的不同而有所不同。要求特定字體的應用程式可以使用 createFont 方法來捆綁這些字體,並對其進行實例化。

邏輯字體

邏輯字體是由必須受所有 Java 執行時間環境支援的 Java 平台所定義的五種字體系列:Serif、SansSerif、Monospaced、Dialog 和 DialogInput。這些邏輯字體不是實際的字體庫。此外,由 Java 執行時間環境將邏輯字體名稱對應到實體字體。映射關係與實現和通常語言環境相關,因此它們提供的外觀和規格各不相同。通常,為了覆蓋龐大的字元範圍,每種邏輯字體名稱都會對應到幾種實體字體。

问题解决

debug的源码很多,但是此次问题的关键点就在这里了,其它debug内容就不贴了。
既然已经确认了本地(mac环境)是native的代码帮我们做了物理字体的封装,转换成了CFont进行渲染,而Linux环境的X11FontManager只是帮我们加载了物理字体和逻辑字体,但是却需要我们自己进行选择,那么解决问题的第一步就显而易见了:将Font的创建从物理字体改为逻辑字体

1 //  Serif、SansSerif、Monospaced、Dialog 和 DialogInput 随意选择
2 Font font = new Font("Serif", Font.PLAIN, 10);

改完以后执行代码,仍然是乱码!继续Debug,发现是Linux上逻辑字体Serif映射的物理字体没有中文字体和对应的特殊符号字体,这就很简单了,直接在Linux上安装中文字体(simsun.ttf),再安装特殊符号“ꐚꌒꑿꆺ”可显示的字体(mysi.ttf),将这两个字体也放到了jdk的fonts目录(JAVA_HOME/jre/lib/fonts)下。文章后面有Linux字体安装方法。

完成上面的改动之后,重启服务,再次执行成功显示!热烈庆祝~~~~

JVM逻辑字体映射配置

以上的改动已经可以解决中文和特殊字符乱码问题,但是我在Debug过程中发现在逻辑字体加载过程中,JVM会参考一个配置文件,代码在sun.awt.FontConfiguration中,这个配置类完成了逻辑字体和物理字体的映射,也指导了SunFontManager创建逻辑字体,而这个FontConfiguration读取的配置文件就是fontconfig.properties,这个配置文件目录是JAVA_HOME/jre/lib

查阅了一下资料,JVM字体配置文件的加载顺序如下:
JAVA_HOME/jre/lib/fontconfig.OS.Version.properties
JAVA_HOME/jre/lib/fontconfig.OS.Version.bfc
JAVA_HOME/jre/lib/fontconfig.OS.properties
JAVA_HOME/jre/lib/fontconfig.OS.bfc
JAVA_HOME/jre/lib/fontconfig.Version.properties
JAVA_HOME/jre/lib/fontconfig.Version.bfc
JAVA_HOME/jre/lib/fontconfig.properties
JAVA_HOME/jre/lib/fontconfig.bfc

OS是系统,例如:Linux、CentOs、RedHat等;Version是版本号

在这个配置文件中可以修改逻辑字体与物理字体的对应关系,也就是说可以手动的修改Serif、SansSerif、Monospaced、Dialog 和 DialogInput这五个逻辑字体在不同场景下所使用的真正物理字体。

举个栗子,下面的配置将serif.plain逻辑字体的中文使用simsun.ttf,拉丁文使用java自带字体:

# @(#)linux.fontconfig.SuSE.properties 1.2 03/10/17
#
# Copyright 2003 Sun Microsystems, Inc. All rights reserved.
#

# Version
version=1

# Component Font Mappings
serif.plain.chinese=-misc-simsun-medium-r-normal--*-%d-*-*-c-*-iso10646-1
serif.plain.latin-1=-b&h-lucidabright-medium-r-normal--*-%d-*-*-p-*-iso8859-1

# Search Sequences
sequence.allfonts=latin-1,chinese

# Exclusion Ranges

# Font File Names
filename.-misc-simsun-medium-r-normal--*-%d-*-*-c-*-iso10646-1=/usr/share/fonts/myfonts/simsun.ttf

Linux安装字体

  • Linux字体目录:/usr/share/fonts
  • 在fonts下面新建一个目录,例如:mkdir myfonts
  • 将需要安装的字体放到新建目录下面,例如:cp ~/test/simsun.ttf /usr/share/fonts/myfonts
  • 进入到myfonts目录:cd /usr/share/fonts/myfonts
  • 执行如下命令:
    • mkfontscale
    • mkfontdir
    • fc-cache -fv
  • 查看是否已经安装对应的字体:fc-list
  • fc-cache -fv 命令用来刷新linux的字体缓存,使其立刻生效

PS:以上所有操作基本都需要root权限

推荐学习:《linux视频教程

以上是如何解決java linux檔中文亂碼問題的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
Linux的5支支柱:了解他們的角色Linux的5支支柱:了解他們的角色Apr 11, 2025 am 12:07 AM

Linux系統的五大支柱是:1.內核,2.系統庫,3.Shell,4.文件系統,5.系統工具。內核管理硬件資源並提供基本服務;系統庫為應用程序提供預編譯函數;Shell是用戶與系統交互的接口;文件系統組織和存儲數據;系統工具用於系統管理和維護。

Linux維護模式:工具和技術Linux維護模式:工具和技術Apr 10, 2025 am 09:42 AM

在Linux系統中,可以通過在啟動時按特定鍵或使用命令如“sudosystemctlrescue”進入維護模式。維護模式允許管理員在不受干擾的情況下進行系統維護和故障排除,如修復文件系統、重置密碼、修補安全漏洞等。

關鍵Linux操作:初學者指南關鍵Linux操作:初學者指南Apr 09, 2025 pm 04:09 PM

Linux初學者應掌握文件管理、用戶管理和網絡配置等基本操作。 1)文件管理:使用mkdir、touch、ls、rm、mv、cp命令。 2)用戶管理:使用useradd、passwd、userdel、usermod命令。 3)網絡配置:使用ifconfig、echo、ufw命令。這些操作是Linux系統管理的基礎,熟練掌握它們可以有效管理系統。

如何使用sudo向Linux的用戶授予高架特權?如何使用sudo向Linux的用戶授予高架特權?Mar 17, 2025 pm 05:32 PM

本文解釋瞭如何管理Linux中的Sudo特權,包括授予,撤銷和安全性最佳實踐。關鍵重點是安全和sudoers安全和限制訪問。Character數量:159

如何在Linux中實現SSH的兩因素身份驗證(2FA)?如何在Linux中實現SSH的兩因素身份驗證(2FA)?Mar 17, 2025 pm 05:31 PM

本文提供了有關使用Google Authenticator在Linux上設置兩因素身份驗證(2FA)的指南,詳細介紹了安裝,配置和故障排除步驟。它突出了2FA的安全益處,例如增強的SEC

如何使用TOP,HTOP和VMSTAT等工具來監視Linux中的系統性能?如何使用TOP,HTOP和VMSTAT等工具來監視Linux中的系統性能?Mar 17, 2025 pm 05:28 PM

本文討論了使用TOP,HTOP和VMSTAT監視Linux系統性能,並詳細介紹其獨特功能和自定義選項,以進行有效的系統管理。

如何使用軟件包管理器(APT,YUM,DNF)管理Linux中的軟件包?如何使用軟件包管理器(APT,YUM,DNF)管理Linux中的軟件包?Mar 17, 2025 pm 05:26 PM

文章討論了使用APT,YUM和DNF在Linux中管理軟件包,涵蓋安裝,更新和刪除。它比較了它們對不同分佈的功能和適用性。

如何在Linux中使用正則表達式(REGEX)進行模式匹配?如何在Linux中使用正則表達式(REGEX)進行模式匹配?Mar 17, 2025 pm 05:25 PM

本文介紹瞭如何在Linux中使用正則表達式(REGEX)進行模式匹配,文件搜索和文本操作,詳細列式,命令和工具,例如GREP,SED和AWK。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
3 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。

EditPlus 中文破解版

EditPlus 中文破解版

體積小,語法高亮,不支援程式碼提示功能

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境