目次
発生した問題
jdk1.8 sun ソース コードのダウンロード
問題の特定
问题解决
JVM逻辑字体映射配置
Linux安装字体
ホームページ 運用・保守 Linuxの運用と保守 Java Linuxファイルの中国語文字化け問題を解決する方法

Java Linuxファイルの中国語文字化け問題を解決する方法

Dec 14, 2021 pm 02:33 PM
java linux

Java linux ファイルの中国語文字化けの解決策: 1. jdk1.8 の sun ソース コードをダウンロードする; 2. フォントの作成を物理フォントから論理フォントに変更する; 3. サービスを再起動する。

Java Linuxファイルの中国語文字化け問題を解決する方法

この記事の動作環境: linux5.9.8 システム、jdk1.8、Dell G3 コンピューター。

Java linux ファイルの中国語文字化けの問題を解決するにはどうすればよいですか?

Linux 環境での Java 中国語文字化けの解決方法

Java で文字化けに遭遇した友人は多いと思いますが、私も最近、「テキストを使用して画像を生成する過程で中国語や特殊文字が文字化けする」問題を解決しました。デバッグに非常に時間がかかりました。 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);
}
ログイン後にコピー

目標はもちろんオープン テストです。 .png で、次のようなシーンが見られました:

ローカル デバッグが問題なかった後、テスト マシン (Linux) に配置して実行しました。結果は単純に圧倒的です:

jdk1.8 sun ソース コードのダウンロード

プログラマーの一貫したスタイルに従います。問題がある場合は、デバッグしてください。
重要なのは、現在のソース コード パッケージには sun パッケージのコードが含まれていないということです。
幸いなことに、OpenJDK のコードは基本的に JVM のソース コードと同じであることが Java によって公式に確認されており、OpenJDK8u から直接ダウンロードできます: jdk8u

ソース コードを使用してデバッグする方法については、これは書きません...これは基本的ですらないので、この記事は読まないでください

問題の特定

ソース コードを直接ダウンロードし、リモート ブレークポイントを使用して、サーバーを実行します。デバッグ中に、ローカル サーバーとテスト サーバーの間で不一致を引き起こす最初のコードを初めて発見しました。

JVM がフォントを作成するときに、FontManagerFactory を使用してフォントを取得することがわかりました。 FontManager であり、異なるシステムでは異なる FontManager が使用されます。 Mac は CFontManager を使用しますが、Linux は X11FontManager を使用します。

それでは、これら 2 つの FontManager の違いは何でしょうか?

CFontManager は CFont を Font2D として作成します。この CFont は Mac 専用に JVM によって作成されたクラスです。クラスとメソッドのコメントを見ると、Mac では物理フォントが CFont によってラップされる場合があることがわかります。

X11FontManager によって作成された Font2D は、論理フォントと物理フォントを含むコレクションです。 X11FontManagerはFcFontManagerを継承し、FcFontManagerはSunFontManagerを継承します。SunFontManagerのloadFonts()を直接使用するX11FontManagerのloadFonts()メソッドを見てみましょう。SunFontManagerのloadFonts()メソッドは物理フォントをロードします。SunFontManagerはFontManagerのpreferLocaleFonts()を実装します。ロードされた論理フォント:

#論理フォントと物理フォント

ここでのコード デバッグ Bian は基本的に、次のことを確認しました。さまざまな環境でのフォント読み込みの問題 では、Linux 環境のデバッグ時に検出される論理フォントと物理フォントとは何でしょうか?

物理フォント

物理フォントは、TrueType や PostScript Type 1 などのフォント テクノロジを使用して文字のシーケンスをグリフのシーケンスにマップするグリフ データとテーブルを含む実際のフォント ライブラリです。 Java プラットフォームのすべての実装は TrueType フォントをサポートしますが、他のフォント テクノロジのサポートは実装に依存します。物理フォントでは、Helvetica、Palatino、HonMincho などのフォント名、またはその他の任意の数のフォント名を使用できます。通常、各物理フォントは、ラテン文字のみ、または日本語と基本ラテン文字のみなど、限られたセットの書記体系のみをサポートします。使用可能な物理フォントのセットは構成によって異なります。特定のフォントを必要とするアプリケーションは、createFont メソッドを使用してこれらのフォントをバンドルし、インスタンス化できます。

論理フォント

論理フォントは、Java プラットフォームによって定義された 5 つのフォント ファミリであり、すべての 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 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Deepseek Webバージョンの入り口Deepseek公式ウェブサイトの入り口 Deepseek Webバージョンの入り口Deepseek公式ウェブサイトの入り口 Feb 19, 2025 pm 04:54 PM

DeepSeekは、Webバージョンと公式Webサイトの2つのアクセス方法を提供する強力なインテリジェント検索および分析ツールです。 Webバージョンは便利で効率的であり、公式ウェブサイトは包括的な製品情報、ダウンロードリソース、サポートサービスを提供できます。個人であろうと企業ユーザーであろうと、DeepSeekを通じて大規模なデータを簡単に取得および分析して、仕事の効率を向上させ、意思決定を支援し、イノベーションを促進することができます。

DeepSeekをインストールする方法 DeepSeekをインストールする方法 Feb 19, 2025 pm 05:48 PM

DeepSeekをインストールするには、Dockerコンテナ(最も便利な場合は、互換性について心配する必要はありません)を使用して、事前コンパイルパッケージ(Windowsユーザー向け)を使用してソースからコンパイル(経験豊富な開発者向け)を含む多くの方法があります。公式文書は慎重に文書化され、不必要なトラブルを避けるために完全に準備します。

Java 8 Stream Foreachから休憩または戻ってきますか? Java 8 Stream Foreachから休憩または戻ってきますか? Feb 07, 2025 pm 12:09 PM

Java 8は、Stream APIを導入し、データ収集を処理する強力で表現力のある方法を提供します。ただし、ストリームを使用する際の一般的な質問は次のとおりです。 従来のループにより、早期の中断やリターンが可能になりますが、StreamのForeachメソッドはこの方法を直接サポートしていません。この記事では、理由を説明し、ストリーム処理システムに早期終了を実装するための代替方法を調査します。 さらに読み取り:JavaストリームAPIの改善 ストリームを理解してください Foreachメソッドは、ストリーム内の各要素で1つの操作を実行する端末操作です。その設計意図はです

Bitget公式ウェブサイトのインストール(2025初心者ガイド) Bitget公式ウェブサイトのインストール(2025初心者ガイド) Feb 21, 2025 pm 08:42 PM

Bitgetは、スポット取引、契約取引、デリバティブなど、さまざまな取引サービスを提供する暗号通貨交換です。 2018年に設立されたこのExchangeは、シンガポールに本社を置き、安全で信頼性の高い取引プラットフォームをユーザーに提供することに取り組んでいます。 Bitgetは、BTC/USDT、ETH/USDT、XRP/USDTなど、さまざまな取引ペアを提供しています。さらに、この取引所はセキュリティと流動性について評判があり、プレミアム注文タイプ、レバレッジド取引、24時間年中無休のカスタマーサポートなど、さまざまな機能を提供します。

OUYI OKXインストールパッケージが直接含まれています OUYI OKXインストールパッケージが直接含まれています Feb 21, 2025 pm 08:00 PM

世界をリードするデジタル資産交換であるOuyi Okxは、安全で便利な取引体験を提供するために、公式のインストールパッケージを開始しました。 OUYIのOKXインストールパッケージは、ブラウザに直接インストールでき、ユーザー向けの安定した効率的な取引プラットフォームを作成できます。インストールプロセスは、簡単で理解しやすいです。

Java をシンプルに: プログラミング能力を高める初心者向けガイド Java をシンプルに: プログラミング能力を高める初心者向けガイド Oct 11, 2024 pm 06:30 PM

Java をシンプルに: プログラミング能力の初心者向けガイド はじめに Java は、モバイル アプリケーションからエンタープライズ レベルのシステムに至るまで、あらゆるもので使用される強力なプログラミング言語です。初心者にとって、Java の構文はシンプルで理解しやすいため、プログラミングの学習に最適です。基本構文 Java は、クラスベースのオブジェクト指向プログラミング パラダイムを使用します。クラスは、関連するデータと動作をまとめて編成するテンプレートです。簡単な Java クラスの例を次に示します。 publicclassperson{privateStringname;privateintage;

未来を創る: まったくの初心者のための Java プログラミング 未来を創る: まったくの初心者のための Java プログラミング Oct 13, 2024 pm 01:32 PM

Java は、初心者と経験豊富な開発者の両方が学習できる人気のあるプログラミング言語です。このチュートリアルは基本的な概念から始まり、高度なトピックに進みます。 Java Development Kit をインストールしたら、簡単な「Hello, World!」プログラムを作成してプログラミングを練習できます。コードを理解したら、コマンド プロンプトを使用してプログラムをコンパイルして実行すると、コンソールに「Hello, World!」と出力されます。 Java の学習はプログラミングの旅の始まりであり、習熟が深まるにつれて、より複雑なアプリケーションを作成できるようになります。

カプセルの量を見つけるためのJavaプログラム カプセルの量を見つけるためのJavaプログラム Feb 07, 2025 am 11:37 AM

カプセルは3次元の幾何学的図形で、両端にシリンダーと半球で構成されています。カプセルの体積は、シリンダーの体積と両端に半球の体積を追加することで計算できます。このチュートリアルでは、さまざまな方法を使用して、Javaの特定のカプセルの体積を計算する方法について説明します。 カプセルボリュームフォーミュラ カプセルボリュームの式は次のとおりです。 カプセル体積=円筒形の体積2つの半球体積 で、 R:半球の半径。 H:シリンダーの高さ(半球を除く)。 例1 入力 RADIUS = 5ユニット 高さ= 10単位 出力 ボリューム= 1570.8立方ユニット 説明する 式を使用してボリュームを計算します。 ボリューム=π×R2×H(4

See all articles