简单介绍编码

Unicode:是容纳世界所有文字符号的国标标准编码,使用四个字节为每个字符编码

UTF:是英文 Unicode Transformation Format 的缩写,意为把 Unicode 字符转换为某种格式。UTF系列编码方
案(UTF-8、UTF-16、UTF-32)均是由 Unicode 编码方案衍变而来,以适应不同的数据存储或传递,它们都可以完全
表示 Unicode 标准中的所有字符。目前,这些衍变方案中 UTF-8 被广泛使用,而 UTF-16 和 UTF-32 则很少被使用。

UTF-8 使用一至四个字节为每个字符编码,其中大部分汉字采用三个字节编码,少量不常用汉字采用四个字节编码。
因为 UTF-8 是可变长度的编码方式,相对于 Unicode 编码可以减少存储占用的空间,所以被广泛使用。

UTF-16 使用二或四个字节为每个字符编码,其中大部分汉字采用两个字节编码,少量不常用汉字采用四个字节编码。
UTF-16 编码有大尾序和小尾序之别,即 UTF-16BE 和 UTF-16LE,在编码前会放置一个 U+FEFF 或 U+FFFE
(UTF-16BE 以 FEFF 代表,UTF-16LE 以 FFFE 代表),其中 U+FEFF 字符在 Unicode 中代表的意义
是 ZERO WIDTH NO-BREAK SPACE,顾名思义,它是个没有宽度也没有断字的空白。

UTF-32 使用四个字节为每个字符编码,使得 UTF-32 占用空间通常会是其它编码的二到四倍。
UTF-32 与 UTF-16 一样有大尾序和小尾序之别,编码前会放置 U+0000FEFF 或 U+0000FFFE 以区分。

乱码的原因

文件要保存在硬盘上就必须要以某种编码方式进行保存,一般都是按照操作系统默认的编码格式进行保存,现在我们
假设要创建一个文件a
1. 打开编辑器
2. 输入中文字符+英文字符。这时字符存储在编辑器所在进程的内存之中(以编辑器自身在内存中存储字符的编码格式
存储字符在内存上,假设在内存中字符以utf-8编码方式保存)
3. 保存到硬盘上。选择格式为gbk,编辑器自动且正确(除非编辑器本身有问题)将内存中utf-8编码的字符转换成gbk
编码保存到硬盘上,字符内容保持不变(无乱码),只是格式换了一下(就像西班牙语的”hello”转换成了希腊语的”hello”)
4. 选择文本浏览工具打开文件a。打开文件时选择读取文件的编码格式为utf-8,这时就出现问题了,以gbk编码保存的文件a
实际上就是”你好,hello”这句话的gbk格式的16进制数字,然后用utf-8读取16进制的方式读取它必然出现乱码(等同于一句西班牙语
你用希腊语的语法去读,肯定都不懂)

综上,出现乱码的原因是:文件保存编码格式和读取编码格式的不匹配造成的

java编码存在两方面内容:JVM之外和JVM之内

JVM之外:java源文件(.java)和编译后的.class文件,源文件可以采用多种编码格式如utf-8(unix linux平台默认)
或者gbk(windows平台默认),当将源码用javac编译的时候,默认是javac按照系统默认的编码格式读取java源文件,
然后以utf-8的格式输出到.class文件中,换句话说,在默认情况下unix平台,javac用utf-8格式读取java源文件
然后以utf-8格式写.class;在默认情况下windows平台,javac用gbk格式读取java源文件然后以utf-8格式写.class

但是如果说源文件的编码格式不采用操作系统默认格式呢?如在windows平台下用utf-8格式保存java源文件(一般ide中
都有选项选择文件保存编码格式),如果不采用ide,直接用javac(javac)编译该源文件,则会造成乱码

/**
* windows 平台下用utf-8保存,同时直接用javac编译
* (不要用ide,ide会智能根据文件编码格式告诉javac用正确的方式便宜)
* 发现乱码
*/
public class Main {
public static void main(String[] args) {
String a = "中";
System.out.println(a);
System.out.println(a.toCharArray().length); //1
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

因此这里的编码转换牵扯到3步 以utf-8保存源文件,以gbk读取源文件,再以utf-8保存.class文件 第二步就出错了等于将utf-8转gbk的乱码以utf-8写,那么必然是乱码,至于如何告诉javac我的原文件是什么编码格式的javac -Dfile.encoding=xxx xx.java 就行了

JVM之内:当运行java字节码时,读入到内存里的字符或者字符串都用charchar[]表示,而char是采用utf-16的
但不是真正的utf-16,为什么这样说? char在java里一直是16位的也就是说只能表示带utf-16的0x0000-0xFFFF(BMP
basic multilingual plane)为止,当对于超过16位的utf-16字符来说(比如表情符号)就需要多个char

public class Main {
public static void main(String[] args) {
String a = new String(new byte[]{(byte)0xF0, (byte)0x9F, (byte)0x98, (byte)0x81});
System.out.println(a);
System.out.println(a.toCharArray().length); //2
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

概括一点说,在JVM中运行时字符串是char[],字符是char 永远的16位,以utf-16(2-4字节)编码但只截取了低16位
截取的结果与unicode(永远的4字节)的低16位同

public class Main {
public static void main(String[] args) {
String a = "中";
System.out.println(a.toCharArray().length); //1
System.out.println(Integer.toHexString(a.toCharArray()[0])); //4e2d
char b = '中';
System.out.println(Integer.toHexString(b)); //4e2d
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

此网站查询字符的各种编码值

stackoverflow中的解释
- A Java char takes always 16 bits.
- A Unicode character, when encoded as UTF-16, takes “almost always” (not always) 16 bits: that’s because there are more than 64K unicode characters. Hence, a Java char is NOT a Unicode character (though “almost always” is).
- “Almost always”, above, means the 64K first code points of Unicode, range 0x0000 to 0xFFF (BMP), which take 16 bits in the UTF-16 encoding.
- A non-BMP (“rare”) Unicode character is represented as two Java chars (surrogate representation). This applies also to the literal representation as a string: For example, the character U+20000 is written as “\uD840\uDC00”.
- Corolary: string.length() returns the number of java chars, not of Unicode chars. A string that has just one “rare” unicode character (eg U+20000) would return length() = 2 . Same consideration applies to any method that deals with char-sequences.
- Java has little intelligence for dealing with non-BMP unicode characters as a whole. There are some utility methods that treat characters as code-points, represented as ints eg: Character.isLetter(int ch). Those are the real fully-Unicode methods.

文章知识点与官方知识档案匹配,可进一步学习相关知识
Java技能树首页概览137862 人正在系统学习中

[转帖]java乱码 java使用的编码是utf-8还是utf-16还是unicode的更多相关文章

  1. 深度剖析java编码,彻底解决java乱码问题_1

    理解: 1,Java编译器(即编译成class文件时) 用的是unicode字符集. 2,乱码主要是由于不同的字符集相互转换导致的,理论上各个字符的编码规则是不同的,是不能相互转换的,所以根本解决乱码 ...

  2. java 乱码详解_jsp中pageEncoding、charset=UTF -8"、request.setCharacterEncoding("UTF-8")

    http://blog.csdn.net/qinysong/article/details/1179480 java 乱码详解__jsp中pageEncoding.charset=UTF -8&quo ...

  3. 深入解析java乱码

    1.什么是编码 ,为什么要编码 先前从没有思考这么深入的问题,觉得一切理所当然,直到有一天java的乱码让我跪了,他不在听我的话,到处是乱码,这次我不打算放过它,我要收拾了它. 大家都知道,文本文件, ...

  4. 深入解析java String中getBytes()的编码问题

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/6900536.html Java服务器后台在和Android端App通信时,遇到了两端关于用MD5加密同一包含 ...

  5. java乱码问题处理

    java乱码问题处理 java乱码出现的问题有很多,这里主要解释tomcat,jsp,html,http(get,post请求乱码处理).常见的问题可能是tomcat,http请求乱码问题,对于jsp ...

  6. java文件传输之文件编码和File类的使用

    ---恢复内容开始--- 我们知道,在用户端和服务端之间存在一个数据传输的问题,例如下载个电影.上传个照片.发一条讯息.在这里我们 就说一下文件的传输. 1.文件编码 相信大家小时候玩过积木(没玩过也 ...

  7. Java几种常见的编码方式

    几种常见的编码格式 为什么要编码 不知道大家有没有想过一个问题,那就是为什么要编码?我们能不能不编码?要回答这个问题必须要回到计算机是如何表示我们人类能够理解的符号的,这些符号也就是我们人类使用的语言 ...

  8. Java基础-二进制以及字符编码简介

    Java基础-二进制以及字符编码简介 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 想必计算机毕业的小伙伴或是从事IT的技术人员都知道数据存储都是以二进制的数字存储到硬盘的.从事开 ...

  9. Java实现哈夫曼编码和解码

    最近无意中想到关于api返回值加密的问题,譬如我们的api需要返回一些比较敏感或者重要不想让截获者得到的信息,像如果是做原创图文的,文章明文返回的话则有可能被抓包者窃取. 关于请求时加密的方式比较多, ...

  10. Java乱码解决

    简述 乱码是JAVA开发时经常遇到的问题.主要出现在四种情况: 1.         系统接口之间 2.         POST提交数据 3.         GET提交数据和URL路径 4.    ...

随机推荐

  1. 从零玩转设计模式之外观模式-waiguanmos

    title: 从零玩转设计模式之外观模式 date: 2022-12-12 15:49:05.322 updated: 2022-12-23 15:34:40.394 url: https://www ...

  2. 动态规划问题(六)最长公共子序列(LCS)

    问题描述 ​ 给你两个字符串,要求得到这两个字符串的最长公共子序列长度. ​ 比如:对于输入的字符串 S1 "AGGTAB" 和 S2 "GXTXAYB",它们 ...

  3. 自从安上了“AI”,这些商务经理天天按时下班了

    摘要:能不能用AI来提升合同管理的效率呢?华为公司用自己的AI实践提交了一份教科书级别的答卷. 对于企业的商务精英而言,什么事情令他们既"煎熬"又"开心",既& ...

  4. MPU:鸿蒙轻内核的任务栈的溢出检察官

    摘要:MPU(Memory Protection Unit,内存保护单元)把内存映射为一系列内存区域,定义这些内存区域的维洲,大小,访问权限和内存熟悉信息. 本文分享自华为云社区<鸿蒙轻内核M核 ...

  5. XEngine:深度学习模型推理优化

    摘要:从显存优化,计算优化两个方面来分析一下如何进行深度学习模型推理优化. 本文分享自华为云社区<XEngine-深度学习推理优化>,作者: ross.xw. 前言 深度学习模型的开发周期 ...

  6. SAST + SCA: 结合使用安全升级

    据 SAP 称,当今85%的安全攻击针对的是软件应用程序,因此一些列应用程序安全测试工具也应运而生.为了避免这些恶意攻击,企业通常使用应用程序安全测试工具来去缓解和解决安全风险,而不同的工具对应的使用 ...

  7. 抖音"凶猛"的幕后英雄,火山引擎 DataTester 累计做过 150 万次 A/B 测试

    在国内互联网领域,字节跳动是最为推崇 A/B 测试的公司,旗下"抖音"."今日头条"两大最著名产品,连 APP 的名字都是来源于 A/B 测试. A/B 测试( ...

  8. Axure 安装使用 FontAwesome

    Axure 安装使用 FontAwesome. 字体下载:https://www.bootcss.com/p/font-awesome/ 解压后,到 font 目录,双击 FontAwesome.ot ...

  9. 玩转Python:在Python中处理表格数据,几个非常流行且功能强大的库

    在Python中处理表格数据,有几个非常流行且功能强大的库.以下是一些最常用的库及其示例代码: 1. Pandas Pandas是一个开放源代码的.BSD许可的库,为Python编程语言提供高性能.易 ...

  10. Go--发起HTTP请求

    一.HTTP请求 根据 HTTP 标准,HTTP 请求可以使用多种请求方法.在日常开发中大多数会用到 5 种请求方法: GET.POST.PUT.PATCH 和 DELETE 方法 描述 GET 请求 ...