Rumah > Artikel > Operasi dan penyelenggaraan > Bagaimana untuk menyelesaikan masalah aksara Cina bercelaru dalam fail Java Linux
Penyelesaian kepada aksara Cina yang kacau dalam fail Linux Java: 1. Muat turun kod sumber matahari jdk1.8 2. Tukar penciptaan fon daripada fon fizikal kepada fon logik 3. Mulakan semula perkhidmatan.
Persekitaran pengendalian artikel ini: sistem linux5.9.8, jdk1.8, komputer Dell G3.
Bagaimana untuk menyelesaikan masalah aksara Cina bercelaru dalam fail Java Linux?
Penyelesaian untuk aksara bercelaru Cina Jawa dalam persekitaran Linux
Saya percaya ramai rakan yang saya temui watak bercelaru di Jawa Baru-baru ini, saya juga telah menyelesaikan masalah "aksara Cina yang kacau dan istimewa dalam proses menggunakan teks untuk menjana imej. Saya mengambil banyak masa untuk nyahpepijat pelbagai kod sumber di bawah sun.font dan sun.awt , akhirnya memahami mekanisme itu dan menyelesaikan masalah semasa sekarang tuliskan proses penyelesaian masalah dan buat rekod untuk mengelak daripada menghadapinya lagi pada masa hadapan.
Berikut ialah kod yang saya ingin laksanakan (amat dipermudahkan, tetapi maksudnya tetap sama):
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); }
Matlamatnya sudah tentu untuk open Apabila testing.png, saya melihat pemandangan berikut:
Selepas penyahpepijatan setempat tiada masalah, saya meletakkannya pada mesin ujian (Linux) dan melaksanakannya , hasil pelaksanaan sangat mengejutkan:
Patuhi gaya pengaturcara yang konsisten: kerana terdapat masalah, maka Debug!
Caranya ialah pakej kod sumber semasa tidak lagi mengandungi kod pakej matahari!
Nasib baik, Java secara rasmi mengesahkan bahawa kod OpenJDK pada asasnya konsisten dengan kod sumber JVM Anda boleh memuat turunnya terus dari OpenJDK8u: jdk8u
Mengenai cara menggunakan kod sumber untuk nyahpepijat, saya menang. 'Jangan tulis tentangnya... Ini bukan perkara asas pun. Jangan baca artikel ini
Muat turun kod sumber terus, gunakan titik putus jauh dan laksanakan pelayan. Semasa penyahpepijatan, saya mula-mula menemui kod pertama yang menyebabkan ketidakkonsistenan antara pelayan tempatan dan ujian:
Ternyata apabila JVM mencipta Font, ia akan menggunakan FontManagerFactory untuk mendapatkan FontManager, dan sistem yang berbeza menggunakan FontManagers yang berbeza! Mac menggunakan CfontManager, manakala Linux menggunakan X11FontManager!
Jadi apakah perbezaan antara kedua-dua FontManagers ini?
CFontManager akan mencipta Cfont sebagai Font2D CFont ini adalah kelas yang dicipta oleh JVM khusus untuk mac, anda boleh tahu bahawa kadangkala fon fizikal akan dibalut oleh Cfont dalam mac. persekitaran, dan ini dalam bahasa asli Selesai dalam kod:
Font2D yang dicipta oleh X11FontManager ialah koleksi yang mengandungi fon logik dan fon fizikal. X11FontManager mewarisi FcFontManager, dan FcFontManager mewarisi SunFontManager, mari kita lihat kaedah loadFonts() X11FontManager, yang secara langsung menggunakan kaedah loadFonts.LodFonts SunFontManager() SunFontManager kaedah caleFonts() Fon logik yang dimuatkan:
Nyahpepijat kod di sini Bian pada dasarnya telah mengesahkan bahawa ia adalah masalah memuatkan fon dalam persekitaran yang berbeza Jadi apakah fon logik dan fon fizikal yang ditemui semasa menyahpepijat persekitaran Linux?
Fon fizikal ialah perpustakaan fon sebenar yang mengandungi data glif dan jadual yang memetakan jujukan aksara kepada jujukan glif menggunakan teknologi fon seperti TrueType atau PostScript Type 1 . Semua pelaksanaan Platform Java menyokong fon TrueType sokongan untuk teknologi fon lain adalah bergantung kepada pelaksanaan. Fon fizikal boleh menggunakan nama fon seperti Helvetica, Palatino, HonMincho atau sebarang nama fon lain. Biasanya, setiap fon fizikal hanya menyokong set sistem penulisan terhad, contohnya, hanya aksara Latin, atau hanya Jepun dan Latin Asas. Set fon fizikal yang tersedia berbeza-beza bergantung pada konfigurasi. Aplikasi yang memerlukan fon tertentu boleh menggunakan kaedah createFont untuk menggabungkan fon ini dan menjadikannya instantiate.
Fon logik ialah lima keluarga fon yang ditakrifkan oleh platform Java yang mesti disokong oleh semua persekitaran masa jalan Java: Serif, SansSerif, Monospaced, Dialog dan DialogInput. Fon logik ini bukan perpustakaan fon sebenar. Selain itu, persekitaran masa jalan Java yang memetakan nama fon logik kepada fon fizikal. Pemetaan adalah pelaksanaan dan secara amnya bergantung kepada tempat, jadi penampilan dan spesifikasi yang mereka sediakan berbeza-beza. Biasanya, setiap nama fon logik dipetakan kepada beberapa fon fizikal untuk merangkumi julat besar aksara.
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字体安装方法。
完成上面的改动之后,重启服务,再次执行成功显示!热烈庆祝~~~~
以上的改动已经可以解决中文和特殊字符乱码问题,但是我在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
PS:以上所有操作基本都需要root权限
推荐学习:《linux视频教程》
Atas ialah kandungan terperinci Bagaimana untuk menyelesaikan masalah aksara Cina bercelaru dalam fail Java Linux. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!