Java码农的福音:再也不怕乱码了

即便是Java这样成熟的语言,开发者们也常常会遇到一个恼人的问题——乱码。

本文将深入探讨乱码的根本原因,并针对Java开发中的乱码场景提出有效的解决方案,辅以实战代码,让Java程序员从此告别乱码困扰。

一,字符集的故事

1,计算机不懂字符

敲代码时,键盘上输入的是字符,屏幕上显示的是字符,计算机的大脑CPU根本不知道字符是什么,CPU能处理的只有二进制,即数字0和1。

在这里插入图片描述
键盘上敲下的字符并不会直接被CPU处理,而是转换为一个二进制,CPU将这个二进制交给GPU,GPU根据❶二进制对应的数字从❷字库中找到对应的字符,以点阵的方式显示在屏幕上。在计算机内部,字符始终是二进制的形式。

上述过程有两个关键点:
❶二进制对应的数字,是字符的编号,称之为码点
❷字库包含所有字符及其对应的码点,称之为字符编码集

2,4个基本概念

为了更清晰的认知字符的原理,出来上述码点和字符编码集之外,还有2个概念,总共是4个基本概念:

  • 字符集合(Character set):是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等,简单理解就是一个字库,与计算机以及编码无关。

  • 字符编码集(Coded character set):是一组字符对应的编码(即数字),为字符集合中的每一个字符给予一个数字,如 Unicode 为每一个字符分配一个唯一的码点与之一一对应。如下图所示:

在这里插入图片描述

  • 字符编码(Character Encoding):简单理解就是一个映射关系,将字符集对应的码点映射为一个个二进制序列,从而使得计算机可以存储和处理。常见的编码方式有 ASCII 编码、ISO-8859-1(不支持中文)、GBK、GB2312(中国编码,支持中文)、UTF-8 等等。字符编码的本质就是把码点通过一个映射函数转换为另一个数字。

这里大家要思考一个问题,码点不就是一个数字吗?直接转换为二进制不就行了吗,为什么又要转换为另一个数字呢?
答案要从字符集的发展历史说起,因为计算机产生在英语国家,字符比较少,所以只需要一个字节就可以表示所有字符,这个表示所有英文世界的字符就是大名鼎鼎的ASCII字符编码集
当计算机出现在其他国家后,比如中国,ASCII字符编码集无法表示中文字符,因为其最多只能表示128个字符,而中文字符有几万个。所以非英语国家也各自制定了字符集。如果中国大陆的简体字GBK字符编码集,港澳台的繁体字Big5字符编码集,这样全世界就出现了各种各样的字符编码集。
后来,一种包含全世界所有字符的字符编码集出现了,即UTF-32,这个字符集用4个字节来表示一个字符,4个字节最多能容纳超过42亿个字符,远远超过了实际需要。但是这个字符集会浪费大量的存储空间,如对于英文字符,本来只要1个字节,但是使用UTF-32,需要4个字节,扩大了4倍。
④解决这个问题的最佳方案是弹性灵活的根据码点选择不同的编码方式,比如英文字母用一个字节的二进制,中文字母用2个几个的二进制,某些特殊符号用3个或者4个字节存储。此时,情况就变得复杂起来,不能直接用码点对应的二进制来存储了,因为这个二进制不仅要包含码点信息,还要包含二进制的长度信息,因为这个二进制是变长的,可能是一个字节,也可能是2、3、4个字节。于是,字符编码就出现了。

  • 字符集(Charset):包括编码字符集和字符编码,如 ASCII 字符集、ISO-8859-X、GB2312 字符集(简中)、BIG5 字符集(繁中)、GB18030 字符集、Shift-JIS 等,即下文中提到的字符集。多种多样的字符集是出现乱码的罪魁祸首

二,为什么会乱码及其解决方案

1,乱码案例

尽管有UTF-8字符集,但因为各种原因,各个字符集仍然有广泛的应用。于是,乱码的出现了。

比如,大陆的兄弟写了一个文本文件,因为操作系统的原因,默认用GBK保存,这个文件通过邮件发送给了香港的同学,香港的计算机操作系统默认使用Big5字符集,香港同学打开时,出现了乱码。
在这里插入图片描述
根本原因是,相同的码点在GBK字符集和Big5字符集表示不同的字符,比如GBK下“兄”的码点是48019,但是在Big5字符集下,并没有这个码点,就会出现乱码。

总结乱码的一般过程:
①写文件使用字符集A进行编码;
②读文件使用字符集B进行解码;

2,乱码的本质:字符集的牛唇不对马嘴

出现乱码,最根本的原因是编码和解码使用了不同的字符集

3,乱码的解决方案

知道了根本原因之后,解决问题就有了思路,解码和编码使用相同的字符集就可以解决乱码问题。

虽然,乱码的表现方式各种各样,需要我们在处理具体的乱码场景时不断积累经验,但万变不离其宗,根本原因还是编码、解码的字符集不一致导致的。

四,Java乱码的常见场景及解决方案

Java内部使用Unicode(通常是UTF-16)作为字符集,这意味着Java源代码、字符串字面量、以及char类型的变量都默认使用Unicode编码。但在输入输出、网络传输、文件操作等环节,Java需要与外部环境交互,这就容易因为编码不一致而导致乱码。

1. 控制台输出乱码

场景:在IDE(如Eclipse、IntelliJ IDEA)中运行Java程序,控制台输出中文时出现乱码。

原因:IDE使用的默认字符编码与Java虚拟机(JVM)的默认编码不一致。

解决方案

  • 修改IDE设置:在IDE中设置项目的字符编码为UTF-8。
    • 例如,在Eclipse中,可以通过右击项目 > Properties > Resource > Text file encoding 设置为UTF-8。
  • 启动参数设置:通过JVM参数指定编码。
    // 在程序启动参数中添加以下内容
    -Dfile.encoding=UTF-8
    

2. 文件读写乱码

场景:读取或写入含有中文的文本文件时出现乱码。

原因:文件的实际编码与程序中指定的编码不匹配。

解决方案

  • 明确指定编码:使用InputStreamReaderOutputStreamWriter时显式指定字符编码。
    // 写文件示例
    try (FileOutputStream fos = new FileOutputStream("test.txt");
         OutputStreamWriter osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8)) {
        osw.write("你好,世界!");
    }
    
    // 读文件示例
    try (FileInputStream fis = new FileInputStream("test.txt");
         InputStreamReader isr = new InputStreamReader(fis, StandardCharsets.UTF_8)) {
        char[] buffer = new char[1024];
        int len;
        while ((len = isr.read(buffer)) != -1) {
            System.out.print(new String(buffer, 0, len));
        }
    }
    

3. 网络传输乱码

场景:在进行HTTP请求或响应时,中文参数或内容出现乱码。

原因:HTTP协议默认使用ISO-8859-1编码,不支持中文等多字节字符。

解决方案

  • URL编码与解码:对中文参数进行URL编码和解码。

    // 编码
    String encodedParam = URLEncoder.encode("中文参数", StandardCharsets.UTF_8);
    
    // 解码
    String decodedParam = URLDecoder.decode(encodedParam, StandardCharsets.UTF_8);
    
  • 设置Content-Type:在HTTP请求或响应头中指定正确的字符编码。

    对于客户端请求:

    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
    

    对于服务器端响应:

    response.setCharacterEncoding("UTF-8");
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/629763.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

网络安全 会飞的狗狗 网络安全狗是什么

1.概述 网站安全狗是一款集网站内容安全防护、网站资源保护及网站流量保护功能为一体的服务器工具。功能涵盖了网马/木马扫描、防SQL注入、防盗链、防CC攻击、网站流量实时监控、网站CPU监控、下载线程保护、IP黑白名单管理、网页防篡改功能等模块。能够为用户提供实时的网站安…

Redis数据结构-RedisObject

1.7 Redis数据结构-RedisObject Redis中的任意数据类型的键和值都会被封装为一个RedisObject,也叫做Redis对象,源码如下: 1、什么是redisObject: 从Redis的使用者的角度来看,⼀个Redis节点包含多个database&#xff…

我的dcd爬虫-Python

我自己写的dcd爬虫,这个网站比较简单。看了看别人的程序,觉得用起来挺别扭,就自己捣鼓了一天。弄出来了。 这个网站没有反爬,有一些是动态网页,有一些是静态。 首先,获取销量排行榜前300的车型。 import…

JVM—>内存调优(发现问题)

一、什么是内存泄露? 内存溢出和内存泄露 内存泄漏(memoryleak):在Java中如果不再使用一个对象,但是该对象依然在GC ROOT的引用链上,这个对象就不会被垃圾回收器回收,这种情况就称之为内存泄漏。内存泄漏绝大多数情况都是由堆内…

机器学习笔记 KAN网络架构简述(Kolmogorov-Arnold Networks)

一、简述 在最近的研究中,出现了号称传统多层感知器 (MLP) 的突破性替代方案,重塑了人工神经网络 (ANN) 的格局。这种创新架构被称为柯尔莫哥洛夫-阿诺德网络 (KAN),它提出了一种受柯尔莫哥洛夫-阿诺德表示定理启发的函数逼近的方法。 与 MLP 不同,MLP 依赖于各个节…

【计算机毕业设计】springboot二手图书交易系统

随着世界经济信息化、全球化的到来和互联网的飞速发展,推动了各行业的改革。若想达到安全,快捷的目的,就需要拥有信息化的组织和管理模式,建立一套合理、动态的、交互友好的、 高效的二手图书交易系统。当前的信息管理存在工作效率…

Jmeter+Grafana+Prometheus搭建压测监控平台

本文不介绍压测的规范与技术指标,本文是演示针对Jmeter如何将压测过程中的数据指标,通过Prometheus采集存储,并在Granfan平台进行仪表盘展示; 介绍 系统压测属于日常项目开发中的一个测试环节,使用测试工具模拟真实用户行为&…

Facebook企业户/在Facebook上做推广有什么好处?

想到出海,必会想到Facebook作为世界上最大的社交网络,Facebook拥有难以想象的用户数量,流量大到没朋友。近年来也是独立站卖家获取流量的有力工具之一。独立站卖家在Facebook上做广告的好处? Facebook,Google 开企业广…

使用RN的kitten框架的日历组件的修改

官方网页地址 下面就是我参考官方封装的时间日期组件(主要是功能和使用方法,页面粗略做了下,不好看勿怪) import React, {useState} from react; import {StyleSheet, View, TouchableOpacity, SafeAreaView} from react-native; …

Go微服务: 日志系统ELK核心架构设计

微服务日志系统建设 1 )为什么需要日志系统 业务发展越来越庞大,服务器越来越多各种访问日志,应用日志,错误日志量越来越多,无法管理开发人员排查问题,需要到服务器上查日志 2 )Elastic Stack…

文件系统和软硬连接

一、磁盘 磁盘可以存储大量的二进制数据,并且断电后也能保持数据不丢失。因此磁盘是一种永久性存储介质,在计算机中,磁盘是一个外设,也是唯一的机械设备。既然磁盘是一个外设,那么就意味着,磁盘和内存&…

Linux无root配置Node,安装nvm

1. 安装NVM: curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash # 或者,如果你使用wget wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash 对于bash用户,可以运行&…

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-15.6讲 GPIO中断实验-GPIO驱动添加中断处理函数

前言: 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM(MX6U)裸机篇”视频的学习笔记,在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…

Weblogic 管理控制台未授权远程命令执行漏洞(CVE-2020-14882,CVE-2020-14883)

1 漏洞概述 Weblogic Pre-Auth Remote Command Execution 漏洞(CVE-2020-14882, CVE-2020-14883)是针对 Oracle WebLogic Server 的两个安全漏洞。CVE-2020-14882 允许远程用户绕过管理员控制台组件中的身份验证,而 CVE-2020-14883 则允许经…

基于springboot+vue+Mysql的大学生社团活动平台

开发语言:Java框架:springbootJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:…

Web应用开发中查找慢SQL的方法

每条SQL语句在执行时都需要消耗一定的I/O资源,SQL语句执行的快慢直接决定了硬件资源被占用时长的长短,慢SQL一般指查询很慢的SQL语句。在MySQL数据库中,可以通过慢查询来查看所有执行超时的SQL语句。在默认情况下,一般慢SQL是关闭…

基于NIOS-II软核流水灯和串口通信实现

文章目录 一、创建工程二、系统设计1. 在 “component library” 标签栏中找到 “Nios II Processor” 后点击 Add2. 在 ”Component Library” 标签栏中的查找窗口输入 jtag 找到 ”JTAG UART ”,然后点击 Add3. 添加片上存储器 On-Chip Memory(RAM)核4. 查找窗口输…

Keil手动安装编译器V5版本

V5编译器下载:免积分下载 新版的keil不会自动帮你安装V5版本的编译器,但是很多教程很多比赛所用单片机都是V5的编译器,所以用来开以前的或者开源的很多东西编译直接一大堆报错。 吐槽说完了接下来教你怎么解决 打开installer(在…

springboot+vue+mybatis物业管理系统+PPT+论文+讲解+售后

快速发展的社会中,人们的生活水平都在提高,生活节奏也在逐渐加快。为了节省时间和提高工作效率,越来越多的人选择利用互联网进行线上打理各种事务,通过线上物业管理系统也就相继涌现。与此同时,人们开始接受方便的生活…

软件压力测试怎么做

随着信息技术的迅猛发展,软件在各行各业的应用越来越广泛,其稳定性、可靠性和性能表现也受到了越来越多的关注。在这样的背景下,软件压力测试显得尤为重要。本文将详细介绍软件压力测试的概念、目的、方法以及实施步骤,帮助读者更…