简单介绍编码

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. 从零玩转第三方登录之WeChat公众号扫码关注登陆 -wechatgzh

    title: 从零玩转第三方登录之WeChat公众号扫码关注登陆 date: 2022-09-27 22:46:53.362 updated: 2023-03-30 13:28:41.359 url: ...

  2. java中final关键字的使用

              1 :在java中final可以修饰类,方法,变量(包括成员变量和局部变量) 第一点:修饰类 特点:修饰的类不能被继承而且成员变量也是可以根据自己需要设置fianl 但final类 ...

  3. 前端系列:ES6-ES12新语法

    目录 ECMAScript系列:简介 ECMAScript系列:ES6新特性 let 关键字 const 关键字 变量的解构赋值 模板字符串 简化对象写法 箭头函数 参数默认值 rest 参数 spr ...

  4. 遥居前列!华为云GaussDB再获行业权威验证

    摘要:北京国家金融科技认证中心正式公布了2022年通过"分布式数据库金融标准验证"的数据库产品名单.华为云GaussDB金融级分布式数据库以突出的技术优势通过验证,跃然榜上,且测试 ...

  5. 应用火山引擎 DataTester“避坑”,抖音实现用 A/B 实验快速试错

    更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 A/B 测试产品可以说是企业科学决策的基础"设施",能够帮助企业快速迭代产品. 在字节跳动,每 ...

  6. WPF 对Border 边框进行投影

    画一个 Border 对边框进行投影 <Window x:Class="WpfApp1.MainWindow" xmlns="http://schemas.micr ...

  7. xTestRunner

    高颜值测试报告-xTestRunner pip install XTestRunner # test_unit.py import unittest from XTestRunner import H ...

  8. 聊聊损失函数1. 噪声鲁棒损失函数简析 & 代码实现

    今天来聊聊非常规的损失函数.在常用的分类交叉熵,以及回归均方误差之外,针对训练样本可能存在的数据长尾,标签噪声,数据不均衡等问题,我们来聊聊适用不同场景有针对性的损失函数.第一章我们介绍,当标注标签存 ...

  9. 正确理解c# default关键字

    背景 最近QA测试一个我开发的一个Web API时,我意识到之前对C#的default的理解一直是想当然的.具体情况是这样,这个API在某些条件下要返回模型的默认值,写法类似于下面这样 [HttpGe ...

  10. 你真的了解token续期嘛?

    Spring Boot + Vue中的Token续签机制 在现代的全栈应用开发中,Spring Boot作为后端框架和Vue.js作为前端框架的组合非常流行.在这种架构中实现Token续签是保障应用安 ...