java unicode编码转换中文_Java 编码问题系统透彻讲解 UNICODE GBK UTF-8 ISO-8859-1 之间的区别

步骤1:编码概念步骤2:常见编码步骤3:UNICODE和UTF步骤4:Java采用的是Unicode步骤5:一个汉字使用不同编码方式的表现步骤6:文件的编码方式-记事本步骤7:文件的编码方式-eclipse步骤8:用FileInputStream 字节流正确读取中文步骤9:用FileReader 字符流正确读取中文


步骤 1 : 编码概念
计算机存放数据只能存放数字,所有的字符都会被转换为不同的数字。
就像一个棋盘一样,不同的字,处于不同的位置,而不同的位置,有不同的数字编号。
有的棋盘很小,只能放数字和英文
有的大一点,还能放中文
有的“足够”大,能够放下世界人民所使用的所有文字和符号
如图所示,英文字符 A 能够放在所有的棋盘里,而且位置都差不多
中文字符, 中文字符 能够放在后两种棋盘里,并且位置不一样,而且在小的那个棋盘里,就放不下中文

20f2b6fb5d191a7fa0a5068f28cc3f34.png

步骤 2 : 常见编码
工作后经常接触的编码方式有如下几种:ISO-8859-1 ASCII 数字和西欧字母GBK GB2312 BIG5 中文UNICODE (统一码,万国码)
其中
ISO-8859-1 包含 ASCII
GB2312 是简体中文,BIG5是繁体中文,GBK同时包含简体和繁体以及日文。
UNICODE 包括了所有的文字,无论中文,英文,藏文,法文,世界所有的文字都包含其中步骤 3 : UNICODE和UTF
根据前面的学习,我们了解到不同的编码方式对应不同的棋盘,而UNICODE因为要存放所有的数据,那么它的棋盘是最大的。
不仅如此,棋盘里每个数字都是很长的(4个字节),因为不仅要表示字母,还要表示汉字等。
如果完全按照UNICODE的方式来存储数据,就会有很大的浪费。
比如在ISO-8859-1中,a 字符对应的数字是0x61
而UNICODE中对应的数字是 0x00000061,倘若一篇文章大部分都是英文字母,那么按照UNICODE的方式进行数据保存就会消耗很多空间
在这种情况下,就出现了UNICODE的各种减肥子编码, 比如UTF-8对数字和字母就使用一个字节,而对汉字就使用3个字节,从而达到了减肥还能保证健康的效果
UTF-8,UTF-16和UTF-32 针对不同类型的数据有不同的减肥效果,一般说来UTF-8是比较常用的方式
UTF-8,UTF-16和UTF-32 彼此的区别在此不作赘述,有兴趣的可以参考 unicode-百度百科

5892f30082b7ff5ec5528b4f084831fb.png

步骤 4 : Java采用的是Unicode
写在.java源代码中的汉字,在执行之后,都会变成JVM中的字符。
而这些中文字符采用的编码方式,都是使用UNICODE. "中"字对应的UNICODE是4E2D,所以在内存中,实际保存的数据就是十六进制的0x4E2D, 也就是十进制的20013。package stream;public class TestStream {public static void main(String[] args) {String str = "中";}}步骤 5 : 一个汉字使用不同编码方式的表现
以字符 为例,查看其在不同编码方式下的值是多少
也即在不同的棋盘上的位置

c3712ffa3e3a04a0d9a638199a96f69e.png
package stream;
 
import java.io.UnsupportedEncodingException;
 
public class TestStream {
 
 public static void main(String[] args) {
 String str = "中";
 showCode(str);
 }
 
 private static void showCode(String str) {
 String[] encodes = { "BIG5", "GBK", "GB2312", "UTF-8", "UTF-16", "UTF-32" };
 for (String encode : encodes) {
 showCode(str, encode);
 }
 
 }
 
 private static void showCode(String str, String encode) {
 try {
 System.out.printf("字符: "%s" 的在编码方式%s下的十六进制值是%n", str, encode);
 byte[] bs = str.getBytes(encode);
 
 for (byte b : bs) {
 int i = b&0xff;
 System.out.print(Integer.toHexString(i) + "t");
 }
 System.out.println();
 System.out.println();
 } catch (UnsupportedEncodingException e) {
 System.out.printf("UnsupportedEncodingException: %s编码方式无法解析字符%sn", encode, str);
 }
 }
}

步骤 6 : 文件的编码方式-记事本
接下来讲,字符在文件中的保存
字符保存在文件中肯定也是以数字形式保存的,即对应在不同的棋盘上的不同的数字
记事本打开任意文本文件,并且另存为,就能够在编码这里看到一个下拉。ANSI 这个不是ASCII的意思,而是采用本地编码的意思。如果你是中文的操作系统,就会使GBK,如果是英文的就会是ISO-8859-1Unicode UNICODE原生的编码方式Unicode big endian 另一个 UNICODE编码方式UTF-8 最常见的UTF-8编码方式,数字和字母用一个字节, 汉字用3个字节。

2025d74d3dbbd77bd693773f8e2a2ee7.png

步骤 7 : 文件的编码方式-eclipse
eclipse也有类似的编码方式,右键任意文本文件,点击最下面的"property"
就可以看到Text file encoding
也有ISO-8859-1,GBK,UTF-8等等选项。
其他的US-ASCII,UTF-16,UTF-16BE,UTF-16LE不常用。

85a2524f8adc3cfef3c3045923593449.png

步骤 8 : 用FileInputStream 字节流正确读取中文
为了能够正确的读取中文内容
1. 必须了解文本是以哪种编码方式保存字符的
2. 使用字节流读取了文本后,再使用对应的编码方式去识别这些数字,得到正确的字符
如本例,一个文件中的内容是字符,编码方式是GBK,那么读出来的数据一定是D6D0。
再使用GBK编码方式识别D6D0,就能正确的得到字符注: 在GBK的棋盘上找到的字后,JVM会自动找到在UNICODE这个棋盘上对应的数字,并且以UNICODE上的数字保存在内存中。

8502913c45efb6e282acf16aef8669fb.png
package stream;
  
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
  
public class TestStream {
  
 public static void main(String[] args) {
 File f = new File("E:projectj2sesrctest.txt");
 try (FileInputStream fis = new FileInputStream(f);) {
 byte[] all = new byte[(int) f.length()];
 fis.read(all);
  
 //文件中读出来的数据是
 System.out.println("文件中读出来的数据是:");
 for (byte b : all)
 {
 int i = b&0x000000ff;  //只取16进制的后两位
 System.out.println(Integer.toHexString(i));
 }
 System.out.println("把这个数字,放在GBK的棋盘上去:");
 String str = new String(all,"GBK");
 System.out.println(str);
 } catch (IOException e) {
 // TODO Auto-generated catch block
 e.printStackTrace();
 }
  
 }
}

步骤 9 : 用FileReader 字符流正确读取中文
FileReader得到的是字符,所以一定是已经把字节根据某种编码识别成了字符
而FileReader使用的编码方式是Charset.defaultCharset()的返回值,如果是中文的操作系统,就是GBK
FileReader是不能手动设置编码方式的,为了使用其他的编码方式,只能使用InputStreamReader来代替,像这样:new InputStreamReader(new FileInputStream(f),Charset.forName("UTF-8"));
在本例中,用记事本另存为UTF-8格式,然后用UTF-8就能识别对应的中文了。解释: 为什么中字前面有一个?
如果是使用记事本另存为UTF-8的格式,那么在第一个字节有一个标示符,叫做BOM用来标志这个文件是用UTF-8来编码的。

f100455f00d862aa9598b4c8595be941.png
package stream;
 
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
 
public class TestStream {
 
 public static void main(String[] args) throws UnsupportedEncodingException, FileNotFoundException {
 File f = new File("E:projectj2sesrctest.txt");
 System.out.println("默认编码方式:"+Charset.defaultCharset());
 //FileReader得到的是字符,所以一定是已经把字节根据某种编码识别成了字符了
 //而FileReader使用的编码方式是Charset.defaultCharset()的返回值,如果是中文的操作系统,就是GBK
 try (FileReader fr = new FileReader(f)) {
 char[] cs = new char[(int) f.length()];
 fr.read(cs);
 System.out.printf("FileReader会使用默认的编码方式%s,识别出来的字符是:%n",Charset.defaultCharset());
 System.out.println(new String(cs));
 } catch (IOException e) {
 // TODO Auto-generated catch block
 e.printStackTrace();
 }
 //FileReader是不能手动设置编码方式的,为了使用其他的编码方式,只能使用InputStreamReader来代替
 //并且使用new InputStreamReader(new FileInputStream(f),Charset.forName("UTF-8")); 这样的形式
 try (InputStreamReader isr = new InputStreamReader(new FileInputStream(f),Charset.forName("UTF-8"))) {
 char[] cs = new char[(int) f.length()];
 isr.read(cs);
 System.out.printf("InputStreamReader 指定编码方式UTF-8,识别出来的字符是:%n");
 System.out.println(new String(cs));
 } catch (IOException e) {
 // TODO Auto-generated catch block
 e.printStackTrace();
 }
  
 }
}


更多内容,点击了解: https://how2j.cn/k/io/io-encoding/695.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值