Java 字符編碼問題,怎么優雅地解決?

網羅開發(小紅書、快手、視頻號同名)

??大家好,我是 展菲,目前在上市企業從事人工智能項目研發管理工作,平時熱衷于分享各種編程領域的軟硬技能知識以及前沿技術,包括iOS、前端、Harmony OS、Java、Python等方向。在移動端開發、鴻蒙開發、物聯網、嵌入式、云原生、開源等領域有深厚造詣。

圖書作者:《ESP32-C3 物聯網工程開發實戰》
圖書作者:《SwiftUI 入門,進階與實戰》
超級個體:COC上海社區主理人
特約講師:大學講師,谷歌亞馬遜分享嘉賓
科技博主:華為HDE/HDG

我的博客內容涵蓋廣泛,主要分享技術教程、Bug解決方案、開發工具使用、前沿科技資訊、產品評測與使用體驗。我特別關注云服務產品評測、AI 產品對比、開發板性能測試以及技術報告,同時也會提供產品優缺點分析、橫向對比,并分享技術沙龍與行業大會的參會體驗。我的目標是為讀者提供有深度、有實用價值的技術洞察與分析。

展菲:您的前沿技術領航員
👋 大家好,我是展菲!
📱 全網搜索“展菲”,即可縱覽我在各大平臺的知識足跡。
📣 公眾號“Swift社區”,每周定時推送干貨滿滿的技術長文,從新興框架的剖析到運維實戰的復盤,助您技術進階之路暢通無阻。
💬 微信端添加好友“fzhanfei”,與我直接交流,不管是項目瓶頸的求助,還是行業趨勢的探討,隨時暢所欲言。
📅 最新動態:2025 年 3 月 17 日
快來加入技術社區,一起挖掘技術的無限潛能,攜手邁向數字化新征程!


文章目錄

    • 前言
    • 背景:為什么會出現編碼問題?
    • 常見場景分析
      • 控制臺輸出亂碼
      • 文件讀寫亂碼
      • 數據庫存取亂碼
    • 解決方案
      • 統一使用 UTF-8
      • 設置 JVM 參數
      • 數據庫設置字符集
    • 實際案例:亂碼排查經驗
    • 總結

前言

在日常 Java 開發中,字符編碼問題是一個非常常見卻又特別容易踩坑的地方。尤其是在不同操作系統之間切換,或者從前端傳到后端、再到數據庫,編碼沒統一好,中文就會出現“亂碼”。很多同學第一次遇到的時候,會被一大堆奇怪的方塊符號或者問號整崩潰。

這篇文章就帶你一步一步看清楚字符編碼的來龍去脈,并結合可運行的代碼,看看如何在 Java 項目里徹底解決編碼不一致的問題。

背景:為什么會出現編碼問題?

其實原因很簡單:不同系統、不同軟件的默認字符編碼不一樣

  • Windows 上默認編碼是 GBK 或 CP936。
  • Linux、Mac 大部分是 UTF-8。
  • 數據庫可能是 Latin1、GBK 或 UTF-8。
  • Tomcat、IDEA 默認也可能不是 UTF-8。

舉個例子,如果你的 Java 程序里寫了一行中文字符串 "你好",在 UTF-8 下存儲沒問題,但如果有人用 GBK 來讀取,就會直接炸掉,變成“亂碼”。

常見場景分析

控制臺輸出亂碼

在 Windows 的 CMD 下運行 Java 程序時,經常會看到控制臺打印中文是亂碼。這是因為 Windows 控制臺默認用 GBK 編碼,但你的 Java 程序里可能用的是 UTF-8。

public class EncodingDemo {public static void main(String[] args) {String msg = "你好,世界";System.out.println(msg);}
}

在 Linux/Mac 控制臺上運行,大概率沒問題。但在 Windows CMD 里,就會看到一堆奇怪符號。

文件讀寫亂碼

當你從文件里讀中文內容時,如果讀的時候用的編碼和寫的時候不一樣,也會直接出錯。

import java.io.*;public class FileEncodingDemo {public static void main(String[] args) throws Exception {String text = "中文內容測試";// 寫入文件,強制使用 UTF-8try (Writer writer = new OutputStreamWriter(new FileOutputStream("test.txt"), "UTF-8")) {writer.write(text);}// 讀取文件(錯誤示范:不指定編碼)try (BufferedReader reader = new BufferedReader(new FileReader("test.txt"))) {System.out.println("讀到的內容:" + reader.readLine());}// 正確方式:指定 UTF-8try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("test.txt"), "UTF-8"))) {System.out.println("正確讀到的內容:" + reader.readLine());}}
}

運行后你會發現,沒指定編碼時中文是亂碼,指定了 UTF-8 之后就正常了。

數據庫存取亂碼

數據庫也是高頻出錯點,比如 MySQL 默認的 latin1 編碼就很坑。假設表結構是這樣的:

CREATE TABLE user (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(50)
) DEFAULT CHARSET=latin1;

如果你在 Java 里用 UTF-8 往里面寫入 "張三",再讀出來時就會發現已經是亂碼。

解決辦法是:

  • 建庫建表時就指定 utf8mb4
CREATE DATABASE demo DEFAULT CHARSET=utf8mb4;
  • JDBC 連接時也要加上編碼參數:
spring.datasource.url=jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC

解決方案

那我們該怎么統一解決這個問題呢?其實有幾個常見思路:

統一使用 UTF-8

UTF-8 是現在最通用的編碼方式,跨系統兼容性最好。所以最穩妥的做法就是:整個鏈路都統一成 UTF-8
包括:源代碼文件、編譯參數、運行參數、數據庫配置、Tomcat 配置。

比如在 Maven 項目里,你可以在 pom.xml 里強制指定源碼編碼:

<project><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties>
</project>

這樣即便在 Windows 上編譯,結果也不會變。

設置 JVM 參數

如果你發現運行環境默認編碼不是 UTF-8,可以在 JVM 啟動時加上參數:

java -Dfile.encoding=UTF-8 -jar app.jar

這會讓整個 Java 虛擬機的默認編碼改成 UTF-8,很多情況下能一勞永逸。

數據庫設置字符集

在 MySQL 里,推薦直接用 utf8mb4,這樣連 emoji 表情都能存:

ALTER DATABASE demo CHARACTER SET utf8mb4;
ALTER TABLE user CONVERT TO CHARACTER SET utf8mb4;

同時,Java 里的 JDBC 連接也要顯式指定編碼,否則還是會出問題。

實際案例:亂碼排查經驗

我自己就踩過一個坑:在 Windows 下本地開發,數據庫是 utf8mb4,項目里也設了 -Dfile.encoding=UTF-8,一切正常。但是代碼上線到 Linux 服務器后,日志里的中文全是亂碼。排查了半天,最后發現是 日志框架的配置文件沒聲明 UTF-8,導致寫日志文件時被當成系統默認編碼。

后來改了一行配置就好了:

<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><charset>UTF-8</charset><pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>

所以要點就是:不要依賴默認值,凡是涉及到字符集的地方都要顯式聲明 UTF-8

總結

Java 的字符編碼問題,說白了就是“讀和寫不一致”。解決它的核心就是統一,特別是統一用 UTF-8。

  • 源代碼、編譯、運行 JVM 都統一 UTF-8。
  • 文件讀寫時顯式指定編碼。
  • 數據庫用 utf8mb4 并在 JDBC 連接里加上參數。

只要做到這幾點,基本就不會再遇到莫名其妙的亂碼問題。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/922400.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/922400.shtml
英文地址,請注明出處:http://en.pswp.cn/news/922400.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

STL之string類(C++)

1.string類核心定位std::string 本質是對 “字符序列” 的封裝&#xff0c;內部通過動態數組存儲字符&#xff0c;并自動管理內存&#xff08;分配、擴容、釋放&#xff09;&#xff0c;對外提供了簡潔的接口用于字符串的創建、修改、拼接、查找等操作。1.1 使用前提頭文件包含…

[Maven 基礎課程]第一個 Maven 項目

idea 新建一個項目&#xff1a; 來到 New Project 頁面&#xff1a; 這里我們有兩種方式創建 maven 項目&#xff0c;一種是自定義創建&#xff0c;另一種是使用 maven 模版項目創建。 自定義創建 maven 項目 基本配置 Name: first_maven_project 項目名稱&#xff0c;設為 …

uni小程序中使用Echarts圖表

前言 今天雞米花給大家帶來的是在uni里面使用echarts&#xff0c;能夠完美支持和PC端一樣的效果&#xff0c;我這邊的工程是uni轉為微信小程序&#xff0c;用的是vue3vite來寫的&#xff0c;然后實現了豎屏和橫屏的展示方式&#xff0c;好了獻上效果圖。 效果圖 一、引入插件 這…

從FOTA測試到汽車電子安全體系的啟蒙之旅

我是穿拖鞋的漢子,魔都中堅持長期主義的汽車電子工程師。 老規矩,分享一段喜歡的文字,避免自己成為高知識低文化的工程師: 做到欲望極簡,了解自己的真實欲望,不受外在潮流的影響,不盲從,不跟風。把自己的精力全部用在自己。一是去掉多余,凡事找規律,基礎是誠信;二是…

stm32中 中斷和事件的區別

一、核心概念比喻想象一下工廠里的一個報警系統&#xff1a;?中斷 (Interrupt)??&#xff1a;就像火警警報器響了。它的目的是通知管理員&#xff08;CPU&#xff09;??&#xff1a;“著火了&#xff01;”。管理員聽到后&#xff0c;會停下手中的工作&#xff08;保存現場…

深入理解MySQL主從架構中的Seconds_Behind_Master指標

問題&#xff1a;主從延遲與寫后讀不一致 在典型的 MySQL 主從架構下&#xff0c;所有寫操作都會直接進入主庫&#xff0c;而讀操作大多分流到從庫&#xff0c;從而實現讀寫分離&#xff0c;緩解主庫壓力。 然而 MySQL 的復制機制是異步的&#xff1a;主庫先寫入 binlog&#…

MySQL安裝(linux版本)

MySQL安裝&#xff08;linux版本&#xff09; 課程地址 08. 進階-MySQL安裝(linux版本)_嗶哩嗶哩_bilibili 安裝過程中所有需要的程序都放在網盤里了 通過網盤分享的文件&#xff1a;虛擬機 鏈接: https://pan.baidu.com/s/1eLMD2iq1uEujNN7mWs2dIg?pwdckmh 提取碼: ckmh …

OpenCV 圖像雙三次BSpline插值

文章目錄 一、簡介 二、實現代碼 三、實現效果 參考資料 一、簡介 之前我們介紹過BSpline曲線,一條B樣條曲線可以被定義成 n + 1 n+1 n+1個控制點的集合 { Q i } i = 0 n {\{Q_i\}}^{n}_{i=0}

Prometheus+Grafana構建企業級監控方案

1.prometheus工作原理&#xff1a; Prometheus將指標收集并存儲為時間序列數據庫&#xff08;時序數據庫&#xff09;&#xff0c;即指標信息與記錄它的時間戳一起存儲&#xff0c;以及稱為標簽的可選鍵值對。 特性&#xff1a; 具有由指標名稱和鍵/值對識別的時間序列數據的…

第23課:行業解決方案設計

第23課:行業解決方案設計 課程目標 掌握金融、醫療、教育等行業應用 學習領域特定Agent設計 了解行業標準集成 實踐設計行業解決方案 課程內容 23.1 金融行業解決方案 金融Agent系統 class FinancialAgentSystem {constructor() {this.agents =

Go語言快速入門教程(JAVA轉go)——2 環境搭建與入門

安裝go Go官網下載地址&#xff1a;https://golang.org/dl/ 中國區官方鏡像站&#xff08;推薦&#xff09;&#xff1a;https://golang.google.cn/dl/ windows安裝 下載好后選擇安裝路徑即可&#xff0c;安裝完成后&#xff0c;winr 輸入cmd調出命令行窗口&#xff0c;輸入…

ffplay播放pcm

用 ffplay 播放 PCM 裸流時&#xff0c;必須手動告訴它“沒有封裝頭、采樣率、聲道數、采樣格式”四個關鍵點。命令模板如下&#xff1a; ffplay -f <采樣格式> -ar <采樣率> -ac <聲道數> -i <pcm文件>常用組合示例 48 kHz、16 bit、小端、雙聲道 ffp…

【LLM】大模型訓練中的穩定性問題

訓練穩定性問題 &#x1f4cb; 概述 本文檔詳細介紹了在項目中解決訓練穩定性問題的方法、原理分析以及實際應用。涵蓋了梯度裁剪、損失函數優化、數值穩定化處理和學習率調度等關鍵技術。&#x1f6a8; 問題描述 現象: 訓練過程中出現數值不穩定&#xff0c;損失函數波動劇烈 …

【linux系統】6. 基礎開發工具(一)

一. 軟件包管理器 1&#xff09;Linux下安裝軟件的常用方法 1. 源代碼安裝 下載程序的源代碼&#xff0c;本地編譯成二進制文件&#xff0c;拷貝到系統指定路徑下。 2. rpm包安裝 已經編譯好的安裝包&#xff0c;使用rpm對應的指令去安裝&#xff0c;也比較麻煩。 3. 包…

ffplay數據結構分析

struct VideoState 播放器封裝 typedef struct VideoState {SDL_Thread *read_tid; // 讀線程句柄AVInputFormat *iformat; // 指向demuxerint abort_request; // 1時請求退出播放int force_refresh; // 1時刷新畫面&#xff0c;請求立即刷新畫面的意思int paused; …

OpenCV:銀行卡號識別

目錄 一、項目原理與核心技術 二、環境準備與工具包導入 1. 環境依賴 2. 工具包導入 三、自定義工具類 myutils.py 實現 四、主程序核心流程&#xff08;銀行卡識別.py&#xff09; 1. 命令行參數設置 2. 銀行卡類型映射 3. 輔助函數&#xff1a;圖像展示 五、步驟 1…

基于spark的澳洲光伏發電站選址預測

基于spark的澳洲光伏發電站選址預測項目概況 [&#x1f447;&#x1f447;&#x1f447;&#x1f447;&#x1f447;&#x1f447;&#x1f447;&#x1f447;] 點這里,查看所有項目 [&#x1f446;&#x1f446;&#x1f446;&#x1f446;&#x1f446;&#x1f446;&#x…

Kibana 雙棧網絡(Dual-Stack)支持能力評估

#作者&#xff1a;Unstopabler 文章目錄一&#xff0e;測試目標二&#xff0e;測試環境三&#xff0e;Kibana1、查詢 Kibana pod信息2、查詢Kibana service信息3、Kibana service 設置四&#xff0e;驗證測試1、Kibana 監聽參數設置2、Kibana節點IPv4狀態檢查3、Kibana節點IPv6…

標準CAN幀介紹

標準CAN幀介紹標準CAN&#xff08;Controller Area Network&#xff09;結構1.幀起始&#xff08;SOF-Start Of Frame&#xff09;2.仲裁段&#xff08;Arbitration Field&#xff09;3.控制段&#xff08;Control Field&#xff09;4.數據段&#xff08;Data Field&#xff09…

easyPoi實現動表頭Excel的導入和導出

easyPoi實現動表頭Excel的導入和導出 Maven依賴 !-- EasyPoi 核心依賴 --><dependency><groupId>cn.afterturn</groupId><artifactId>easypoi-base</artifactId><version>4.4.0</version></dependency><!-- EasyPoi Web…