字符集和字符编码

关于乱码:

你们应该都有遇到过这种问题,就是utf-8或者gbk编码格式的中文字符,若转成"iso-8859-1"编码格式,则会变成乱码,为什么呢?那我们得先知道以下知识点。
       1.utf-8存储中文汉字用的是3个字节
       2."gbk"存储中文汉字用的是2个字节
       3.iso-8859-1存储任何字符都是1个字节
       知道这个之后就能原因明朗了,本来是用三个字节或两个字节存的内容,你用一个字节存,这能不出事吗?能不变成乱码吗?
那就转化不了了吗?
我就再想,存不下,那就多分几个字节存呗,汉字总是可以用iso-8859-1编码表示的!

在实际应用中接触比较多的文本编码有3种:ASCIIANSIUNICODE,其中ASCII码是后两种也是大多数常用编码的基础。

1.ASCII(数字和少部分西欧字母) ISO-8859-1  (数字和大部分西欧字母)
2.ANSI(ANSI是一种字符代码,为使计算机支持更多语言,通常使用 0x00~0x7f 范围的1 个字节来表示 1 个英文字符。超出此范围的使用0x80~0xFFFF来编码,即扩展的ASCII编码。)

GB2312(简体中文) BIG5(繁体中文)JIS 编码(日文)GBK(简体和繁体以及日文)

为使计算机支持更多语言,通常使用 0x80~0xFFFF 范围的 2 个字节来表示 1 个字符。比如:汉字 '中' 在中文操作系统中,使用 [0xD6,0xD0] 这两个字节存储。

不同的国家和地区制定了不同的标准,由此产生了 GB2312、GBK、GB18030、Big5、Shift_JIS 等各自的编码标准。这些使用多个字节来代表一个字符的各种汉字延伸编码方式,称为 ANSI 编码。在简体中文Windows操作系统中,ANSI 编码代表 GB2312编码;在繁体中文Windows操作系统中,ANSI编码代表Big5;在日文Windows操作系统中,ANSI 编码代表 JIS 编码。

以下是常见的汉字字符集编码GB编码(中文编码)

  1. GB2312编码:1981年5月1日发布的简体中文汉字编码国家标准。GB2312对汉字采用双字节编码,收录7445个图形字符,其中包括6763个汉字。
  2. BIG5编码:台湾地区繁体中文标准字符集,采用双字节编码,共收录13053个中文字,1984年实施。
  3. GBK编码:1995年12月发布的汉字编码国家标准,是对GB2312编码的扩充,对汉字采用双字节编码。GBK字符集共收录21003个汉字,包含国家标准GB13000-1中的全部中日韩汉字,和BIG5编码中的所有汉字。
  4. GB18030编码:2000年3月17日发布的汉字编码国家标准,是对GBK编码的扩充,覆盖中文、日文、朝鲜语和中国少数民族文字,其中收录27484个汉字。GB18030字符集采用单字节、双字节和四字节三种方式对字符编码。兼容GBK和GB2312字符集。

汉字unicode编码表:

字符集字数Unicode 编码范围
基本汉字20902字4E00-9FA5
基本汉字补充38字9FA6-9FCB
扩展A6582字3400-4DB5
扩展B42711字20000-2A6D6
扩展C4149字2A700-2B734
扩展D222字2B740-2B81D
康熙部首214字2F00-2FD5
部首扩展115字2E80-2EF3
兼容汉字477字F900-FAD9
兼容扩展542字2F800-2FA1D
PUA(GBK)部件81字E815-E86F
部件扩展452字E400-E5E8
PUA增补207字E600-E6CF
汉字笔画36字31C0-31E3
汉字结构12字2FF0-2FFB
汉语注音22字3105-3120
注音扩展22字31A0-31BA
1字3007

3.UNICODE (统一码,万国码,每个字符4个字节)  UTF-8(对数字和字母就使用一个字节,而对汉字就使用3个字节),UTF-16和UTF-32 

例:
ANSI 这个不是ASCII的意思,而是采用本地编码的意思。如果你是中文的操作系统,就会使GBK,如果是英文的就会是ISO-8859-1
Unicode UNICODE原生的编码方式
Unicode big endian 另一个 UNICODE编码方式
UTF-8 最常见的UTF-8编码方式,数字和字母用一个字节, 汉字用3个字节。

文件的编码方式-记事本

ASCII

ASCII 是互联网上计算机之间使用的第一个字符集(编码标准)。

ISO-8859-1(在 HTML 4.01 中是默认的)和 UTF-8(在 HTML5 中是默认的)都是基于 ASCII 建立的。

ASCII 全称 "American Standard Code for Information Interchange",即美国信息交换标准编码

它是在 60 年代早期作为计算机和电子设备的标准字符集被设计的。

ASCII 是一种 7 位字符集,包含了 128 个字符

支持 0-9 数字,大/小写英文字母(a-z、A-Z)和一些特殊的字符。

在现代计算机中、HTML 中、互联网上所使用的字符集,都是基于 ASCII。

ISO-8859-1

在 HTML 4.01 中,ISO-8859-1 是默认的字符。

ISO(全称 International Standards Organization 国际标准化组织)为不同的字母/语言定义了标准的字符集。

ISO-8859-1编码是单字节编码,包含了 256个字符

ISO-8859-1 的第一部分(实体编号 0-127)是原来的 ASCII 字符集。它包含数字、大小写英文字母和一些特殊字符。

在 ISO-8859-1 中,未使用从 128 到 159 的编码,但是很多浏览器会显示 ANSI(Windows-1252)字符集的字符,而不是什么都不显示。

编码:

1.Java如何编码:java 是如何编码解码的_w3cschool

以及中文乱码解决

Java使用到的编码:1.char字符、2.io流

2.html字符集:HTML 字符集 | 菜鸟教程

html URL编码:HTML URL 编码参考手册 | 菜鸟教程

URL - 统一资源定位器

Web 浏览器通过 URL 从 web 服务器请求页面。

URL 是网页的地址,比如: http://www.runoob.com


URL 编码

URL 只能使用 ASCII 字符集来通过因特网进行发送。

由于 URL 常常会包含 ASCII 集合之外的字符,URL 必须转换为有效的 ASCII 格式。

URL 编码使用 "%" 其后跟随两位的十六进制数来替换非 ASCII 字符。

URL 不能包含空格。URL 编码通常使用 + 来替换空格。

URL 编码参考手册

HTML URL 编码参考手册 | 菜鸟教程

比如:

但是这个问题的由来呢?

在Java项目连接mysql时,有时需要设置时区,如下:

第一种:jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=CST

第二种:jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=GMT%2B8

所以我们采用第二种
可以看这个问题:CST和GMT时间的区别_kunpengku的博客-CSDN博客

3.JavaScript 字符串的特殊字符

JavaScript 字符串 | 菜鸟教程

总结: 

进制、进制转换
    最高可到64进制,进制转换:https://www.sojson.com/hexconvert/64to2.html(有64无62)、https://tool.lu/hexconvert/?t=1506782329946(有62无64)

编码
    UNICODE、UTF、中文编码(GB2312编码、BIG5编码、GBK编码、GB18030编码)、日文(JIS 编码)、ASCII(数字和少部分西欧字母) 、ISO-8859-1(数字和大部分西欧字母)
    Unicode 是容纳世界所有文字符号的国际标准编码,使用四个字节为每个字符编码。
    UTF 是英文 Unicode Transformation Format 的缩写,意为把 Unicode 字符转换为某种格式。UTF 系列编码方案(UTF-8、UTF-16、UTF-32)均是由 Unicode 编码方案衍变而来,以适应不同的数据存储或传递,它们都可以完全表示 Unicode 标准中的所有字符。目前,这些衍变方案中 UTF-8 和 UTF-16 被广泛使用,而 UTF-32 则很少被使用。
    UTF-8 使用一至四个字节为每个字符编码,其中 Unicode BMP 平面的汉字采用三个字节编码,辅助平面的汉字采用四个字节编码。因为 UTF-8 是可变长度的编码方式,相对于 Unicode 编码可以减少存储占用的空间,所以被广泛使用。
    UTF-16 使用二或四个字节为每个字符编码,其中 Unicode BMP 平面的汉字采用两个字节编码,辅助平面的汉字采用四个字节编码。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+FFFE0000 以区分。
    转换:https://www.qqxiuzi.cn/bianma/Unicode-UTF.php

Codec编码
    Base编码系列:Base64 Base62 Base32 Base16:https://www.qqxiuzi.cn/bianma/base64.htm
    Base64编码是用64(2的6次方)个ASCII字符来表示256(2的8次方)个ASCII字符,也就是三位二进制数组经过编码后变为四位的ASCII字符显示,长度比原来增加1/3。
    Base62编码是由10个数字、26个大写英文字母和26个小写英文字母组成,多用于安全领域和短URL生成。
    Base32就是用32(2的5次方)个特定ASCII码来表示256个ASCII码。所以,5个ASCII字符经过base32编码后会变为8个字符(公约数为40),长度增加3/5.不足8n用“=”补足。

短url
    https://blog.csdn.net/MCmango/article/details/114121289
    https://www.zhihu.com/question/29270034
    方案总结:
    1.主要思路,维护一个全局自增的id,每来一个长url,将其与一个自增id绑定,然后利用base62将该自增id转换为base62字符串,即完成转换。
java字符编码转换研究(转):https://www.cnblogs.com/lxzh/archive/2012/05/30/2526557.html
    url编码、解码
    //URL
    String url = "https://blog.csdn.net/MCmango/article/details/114121289";
    String urlEncode = URLEncoder.encode(url, "UTF-8"); // 编码
    String urlDecode = URLDecoder.decode(urlEncode, "UTF-8"); // 解码


问题:
一.计算机内存为什么用16进制
为什么用16进制
1、计算机硬件是0101二进制的,16进制刚好是2的倍数,更容易表达一个命令或者数据。十六进制更简短,因为换算的时候一位16进制数可以顶4位2进制数,也就是一个字节(8位进制可以用两个16进制表示)
2、最早规定ASCII字符集采用的就是8bit(后期扩展了,但是基础单位还是8bit),8bit用2个16进制直接就能表达出来,不管阅读还是存储都比其他进制要方便
3、计算机中CPU运算也是遵照ASCII字符集,以16、32、64的这样的方式在发展,因此数据交换的时候16进制也显得更好
4、为了统一规范,CPU、内存、硬盘我们看到都是采用的16进制计算

16进制用在哪里
1、网络编程,数据交换的时候需要对字节进行解析都是一个byte一个byte的处理,1个byte可以用0xFF两个16进制来表达。通过网络抓包,可以看到数据是通过16进制传输的。
2、数据存储,存储到硬件中是0101的方式,存储到系统中的表达方式都是byte方式
3、一些常用值的定义,比如:我们经常用到的html中color表达,就是用的16进制方式,4个16进制位可以表达好几百万的颜色信息。


二.java byte定义变量后,当该变量值超过127后,会变成负数,是因为补码的有原因?
byte a = 127;
byte b = (byte) (a + 1);
System.out.println(b); 结果:-128求解释
正是采用补码,称为有符号数。一个字节,127是最大正数,再加1,就超过,变成了-128,最小的负数,称补码溢出,这是补码的特性

byte 长度是1字节,也就是八位,你想想八位二进制数转换为十进制是多少?对是256,如果是unsigned byte 那么取值范围就是 0-255,而这个byte是有符号位的,所以取值范围正负各半 -128——127

byte占一个字节空间,最高位是符号位,剩余7位能表示0-127,加上符号位的正负,就是-127至+127,但负0没必要,为充分利用,就用负零表示-128(即原码1000,0000)。(计算机转补码后存储)


三.Java字符串中常用字符占用字节数
java中一个char型的数据(也就是一个字符)占两个字节。
而Java中常用的字符包括数字、英文字母、英文符号、中文汉字、中文符号等,若在字符串中包含里面的多种字符,它们是否都占两个字符呢?答案是否定的。
String s1 = "1";
System.out.println(s1.getBytes().length); // 1

String s2 = "!";
System.out.println(s2.getBytes().length); // 1

String s3 = "中";
System.out.println(s3.getBytes().length); // 3

四.在编码过程中遇到的问题
需求:生成箱号,不能重复,不能过长
初始采用:当前时间+随机数然后转base62,自以为不错,挺短的,然而根据箱号名称下载的时候,发现不行,虽然字符串没有重复,但是windows系统文件名不区分大小写,导致文件覆盖
优化:最后采用base36
总结:windows系统文件名不区分大小写,注意出现覆盖的情况


实战:
一.进制转换
import java.math.BigDecimal;
import java.math.BigInteger;

/* 进制:注意不是都从数字开始
 * 10进制到62进制数的表示方法:10~35用大写字母A~Z表示,36~61用小写字母a~z表示
 * 2	
 * 8	
 * 10	
 * 16	
 * 26	小写字母
 * 32	不包含 ILOU 字符
 * 36	数字 + 小写字母
 * 52	大写字母 + 小写字母
 * 58	不包含 0OlI 字符
 * 62	数字 + 小写字母 + 大写字母
 */ 
public class BinaryConversion {
	
	//32进制数是由32个数码:数字0~9加上字母A-V组成(它们分别表示十进制数10~31),32进制数运算规律是逢32进1,即基数R=32=2^6。
	private static String s32bit_const = "0123456789ABCDEFGHIJKLMNOPQRSTUV";
	
	private static String s36bit_const = "0123456789abcdefghijklmnopqrstuvwxyz";

	private static String s62bit_const = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
	
	// 36进制
	public static final String ALPHABET_36 = "0123456789abcdefghijklmnopqrstuvwxyz";

	// 62进制
	public static final char[] ALPHABET_62 = {
			'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
			'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
			'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
    		'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
			'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
    		};

	// 64进制
	public static final char[] ALPHABET_64 = {
    		'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
			'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
			'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
			'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
    		'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' };
	
	// 方式一
	/* 
	 * 10进制转32进制
	 */
    public static String to32Binary(BigInteger i) {
        BigDecimal divide = new BigDecimal(32);
        BigDecimal decimal = new BigDecimal(i);
        String res = "";
        while (BigDecimal.ZERO.compareTo(decimal) != 0){
            BigDecimal[] divRes = decimal.divideAndRemainder(divide);
            decimal = divRes[0];
            res =  s32bit_const.charAt(divRes[1].intValue()) + res;
        }
        return res;
    }
    
    /* 
     * 10进制转36进制
     */
    public static String to36Binary(BigInteger i) {
        BigDecimal divide = new BigDecimal(36);
        BigDecimal decimal = new BigDecimal(i);
        String res = "";
        while (BigDecimal.ZERO.compareTo(decimal) != 0){
            BigDecimal[] divRes = decimal.divideAndRemainder(divide);
            decimal = divRes[0];
            res =  s36bit_const.charAt(divRes[1].intValue()) + res;
        }
        return res;
    }
    
    /*
     * 10进制转62进制
     */
    public static String to62Binary(BigInteger i) {
    	BigDecimal divide = new BigDecimal(36);
        BigDecimal decimal = new BigDecimal(i);
        String res = "";
        while (BigDecimal.ZERO.compareTo(decimal) != 0){
            BigDecimal[] divRes = decimal.divideAndRemainder(divide);
            decimal = divRes[0];
            res =  s62bit_const.charAt(divRes[1].intValue()) + res;
        }
        return res;
    }
    
    // 方式二
    /*
     * 10进制转36进制
     */
    public static String to36String(BigInteger i) {
        BigDecimal divide = new BigDecimal(36);
        BigDecimal decimal = new BigDecimal(i);
        String result = "";
        while (BigDecimal.ZERO.compareTo(decimal) != 0){
            BigDecimal[] divRes = decimal.divideAndRemainder(divide);
            decimal = divRes[0];
            result =  ALPHABET_36.charAt(divRes[1].intValue()) + result;
        }
        return result;
    }
    
    /*
     * 10进制转62进制
     */
    public static String to62String(long i) {
        BigDecimal divide = new BigDecimal(62);
        BigDecimal decimal = new BigDecimal(i);
        String result = "";
        while (BigDecimal.ZERO.compareTo(decimal) != 0){
            BigDecimal[] divRes = decimal.divideAndRemainder(divide);
            decimal = divRes[0];
            result =  ALPHABET_62[divRes[1].intValue()] + result;
        }
        return result;
    }
    
    // 方式三
    /*
	 * 10进制的数字转换成64进制
	 */
    public static String CompressNumber(long number) {
		char[] buf = new char[64];
		int charPos = 64;
		int radix = 1 << 6;
		long mask = radix - 1;
		do {
			buf[--charPos] = ALPHABET_64[(int) (number & mask)];
			number >>>= 6;
		} while (number != 0);
		return new String(buf, charPos, (64 - charPos));
	}
    
    /*
     * 36进制字符串转10进制
     */ 
    public static long to10Long(String resource) {
    	long result = 0;
    	char[] resources = resource.toCharArray();
    	int length = resources.length;
    	for(int i=0; i<resources.length; i++) {
    		result += Math.multiplyExact(ALPHABET_36.indexOf(resources[i]), Math.round(Math.pow(36, length-i-1)));
    	}
        return result;
    }

    /*
     * 62进制字符串转10进制
     */ 
    public static long string62to10(String resource) {
    	long result = 0;
    	char[] resources = resource.toCharArray();
    	int length = resources.length;
    	for(int i=0; i<resources.length; i++) {
    		result += Math.multiplyExact(String.valueOf(ALPHABET_62).indexOf(resources[i]), Math.round(Math.pow(62, length-i-1)));
    	}
        return result;
    }
    
	/*
	 * 把64进制的字符串转换成10进制
	 */
	public static long UnCompressNumber(String decompStr) {
		long result = 0;
		for (int i = decompStr.length() - 1; i >= 0; i--) {
			for (int j = 0; j < ALPHABET_64.length; j++) {
				if (decompStr.charAt(i) == ALPHABET_64[j]) {
					result += ((long) j) << 6 * (decompStr.length() - 1 - i);
				}
			}
		}
		return result;
	}
	
	public static void main(String[] args) {
		long number=100l;
		char[] buf = new char[64];
		int charPos = 64;
		int radix = 1 << 6;    // 1000000 64
		long mask = radix - 1; //  111111 63
		do {
			buf[--charPos] = ALPHABET_64[(int) (number & mask)];
			number >>>= 6;
		} while (number != 0);
		System.out.println(new String(buf, charPos, (64 - charPos)));
		
		System.out.println(new String(ALPHABET_62, 3, 3)); 
		
        System.out.println(to36String(BigInteger.valueOf(80)));
        System.out.println(to36String(BigInteger.valueOf(80)));
	}

}

二.java字符编码
System.out.println(Charset.defaultCharset());
byte[] b1 = "中".getBytes();
for(int i=0; i<b1.length; i++) {
    System.out.print(b1[i]+"\t");
}
System.out.println();
byte[] b2 = "中".getBytes("UTF-8");
for(int i=0; i<b2.length; i++) {
    System.out.print(b2[i]+"\t");
}
System.out.println();
byte[] b3 = "中".getBytes("unicode");
for(int i=0; i<b3.length; i++) {
    System.out.print(b3[i]+"\t");
}
System.out.println();
// 在不同字符集下,字符所占的字节数不同
// java文件中文默认使用UFT-8字符集(不应该是unicode吗?因为在eclipse中设置了UTF-8编码)

byte[] bs = "中".getBytes("unicode");
for (byte b : bs) {
    int i = b&0xff;
    System.out.print(b+"--"+Integer.toHexString(i) + "\t");
}
// java字符编码转换研究(转) https://www.cnblogs.com/lxzh/archive/2012/05/30/2526557.html
// java文件本地UTF-8编码(可手动设置)(10进制) -> 编译jvm unicode编码(16进制)所有字符4个字节 -> 操作系统(2进制)
// 在内存中,实际保存的数据就是16进制而不是2进制(为什么不用2进制,计算机只能识别2进制?)
/*
java文件编译后是Class文件十六进制字节码(Class文件十六进制背后的秘密:https://blog.csdn.net/peng_zhanxuan/article/details/104329859)
                疑问:java class文件为什么是16进制而不是2进制?电脑机器只能理解2进制的字节码
                简单理解为:写java程序, 编译后被写成了16进制的class文件, 虚拟机将以上字节码通过解释器解释成汇编指令,最终由硬件转译为CPU能识别的机器指令。(Java虚拟机-Java程序执行流程 -> JVM是如何与操作系统交互的:https://zhuanlan.zhihu.com/p/387617017)
*/

// Unicode是一个字符编码的标准规范,而UTF-8/UTF-16/UTF-32只是对这个标准规范的具体实现。
// Unicode只是给字符作编号,不代表计算机里的编码。只有在计算机里需要处理时,才会用“编码”来表示。而Unicode不是编码,只是代表一个字符的编号

// 字节流和字符流
// 字符流就是对字节流进行包装,字节流读出来的是byte,字符流就是按照摸个编码格式如:utf-8对字节进行编码了,这个过程是自动完成的,无需字节流读出来后,还要编码。

三.java不同编码下,将字符转为字节
    /*
     * 不同编码下,将字符转为字节
     */
    public static void main4(String[] args)  {
    	
    	// 查看java支持的编码
    	System.out.println(JSON.toJSONString(Charset.availableCharsets().keySet()));
    	// ["Big5","Big5-HKSCS","CESU-8","EUC-JP","EUC-KR","GB18030","GB2312","GBK",
    	// "IBM-Thai","IBM00858","IBM01140","IBM01141","IBM01142","IBM01143","IBM01144","IBM01145","IBM01146","IBM01147","IBM01148","IBM01149","IBM037","IBM1026","IBM1047","IBM273","IBM277","IBM278","IBM280","IBM284","IBM285","IBM290","IBM297","IBM420","IBM424","IBM437","IBM500","IBM775","IBM850","IBM852","IBM855","IBM857","IBM860","IBM861","IBM862","IBM863","IBM864","IBM865","IBM866","IBM868","IBM869","IBM870","IBM871",
    	// "IBM918","ISO-2022-CN","ISO-2022-JP","ISO-2022-JP-2","ISO-2022-KR","ISO-8859-1","ISO-8859-13","ISO-8859-15","ISO-8859-2","ISO-8859-3","ISO-8859-4","ISO-8859-5","ISO-8859-6","ISO-8859-7","ISO-8859-8","ISO-8859-9","JIS_X0201","JIS_X0212-1990","KOI8-R","KOI8-U","Shift_JIS","TIS-620",
    	// "US-ASCII","UTF-16","UTF-16BE","UTF-16LE","UTF-32","UTF-32BE","UTF-32LE","UTF-8",
    	// "windows-1250","windows-1251","windows-1252","windows-1253","windows-1254","windows-1255","windows-1256","windows-1257","windows-1258","windows-31j",
    	// "x-Big5-HKSCS-2001","x-Big5-Solaris","x-euc-jp-linux","x-EUC-TW","x-eucJP-Open","x-IBM1006","x-IBM1025","x-IBM1046","x-IBM1097","x-IBM1098","x-IBM1112","x-IBM1122","x-IBM1123","x-IBM1124","x-IBM1166","x-IBM1364","x-IBM1381","x-IBM1383","x-IBM300","x-IBM33722","x-IBM737","x-IBM833","x-IBM834","x-IBM856","x-IBM874","x-IBM875","x-IBM921","x-IBM922","x-IBM930","x-IBM933","x-IBM935","x-IBM937","x-IBM939","x-IBM942","x-IBM942C","x-IBM943","x-IBM943C","x-IBM948","x-IBM949","x-IBM949C","x-IBM950","x-IBM964","x-IBM970","x-ISCII91","x-ISO-2022-CN-CNS","x-ISO-2022-CN-GB","x-iso-8859-11","x-JIS0208","x-JISAutoDetect","x-Johab","x-MacArabic","x-MacCentralEurope","x-MacCroatian","x-MacCyrillic","x-MacDingbat","x-MacGreek","x-MacHebrew","x-MacIceland","x-MacRoman","x-MacRomania","x-MacSymbol","x-MacThai","x-MacTurkish","x-MacUkraine","x-MS932_0213","x-MS950-HKSCS","x-MS950-HKSCS-XP","x-mswin-936","x-PCK","x-SJIS_0213","x-UTF-16LE-BOM","X-UTF-32BE-BOM","X-UTF-32LE-BOM","x-windows-50220","x-windows-50221","x-windows-874","x-windows-949","x-windows-950","x-windows-iso2022jp"
    	// ]
    	
    	// 1.查看默认字符编码
    	System.out.println(Charset.defaultCharset()); // UTF-8
    	
    	// 2.
    	String b1 = "師";
    	byte[] b1s = b1.getBytes(); //UTF-8
    	for(int i=0;i<b1s.length;i++) {
    		System.out.println(b1s[i]);
//    		-28
//    		-72
//    		-83
    	}
    	
    	byte[] UTF16 = b1.getBytes();
    	for(int i=0;i<UTF16.length;i++) {
    		System.out.println(UTF16[i]);
//    		-28
//    		-72
//    		-83
    	}
    	
    	byte[] UTF32 = b1.getBytes();
    	for(int i=0;i<UTF32.length;i++) {
    		System.out.println(UTF32[i]);
//    		-28
//    		-72
//    		-83
    	}

    	byte[] asc2 = b1.getBytes(Charset.forName("ASCII"));
    	for(int i=0;i<asc2.length;i++) {
    		System.out.println(asc2[i]);
//    		63
    	}
    	
    	byte[] iso = b1.getBytes(Charset.forName("iso-8859-1"));
    	for(int i=0;i<iso.length;i++) {
    		System.out.println(iso[i]);
//    		63
    	}
    	
    	byte[] UNICODE =b1.getBytes(Charset.forName("UNICODE"));
    	for(int i=0;i<UNICODE.length;i++) {
    		System.out.println(UNICODE[i]);
//    		-2
//    		-1
//    		78
//    		45
    	}
    	
    	byte[] b3s =b1.getBytes(Charset.forName("GB2312"));
    	for(int i=0;i<b3s.length;i++) {
    		System.out.println(b3s[i]);
//    		-42
//    		-48
    	}
    	
    	byte[] b4s =b1.getBytes(Charset.forName("BIG5"));
    	for(int i=0;i<b4s.length;i++) {
    		System.out.println(b4s[i]);
//    		-92
//    		-92
    	}
    	
    	byte[] b5s =b1.getBytes(Charset.forName("GBK"));
    	for(int i=0;i<b5s.length;i++) {
    		System.out.println(b5s[i]);
//    		-42
//    		-48
    	}
    	
    	
    }

四.base编码转换过程:base64、base32、base62
import cn.hutool.core.codec.Base32;
import cn.hutool.core.codec.Base62;
import cn.hutool.core.codec.Base64;

public class Test {
	
	/*
	 * 字符转base32/base64
	 */
	public static void main1(String[] args)  {
    	byte[] b1 = "中".getBytes();
    	for(int i=0;i<b1.length;i++) {
    		System.out.println(b1[i]); //一个中文3个字节
    		// 正数的二进制为原码,负数的二进制为补码
    		// 数字    原码                      反码(原码取反) 补码(反码+1)
    		// -28 00011100  11100011  11100100
    		// -72 01001000  10110111  10111000
    		// -83 01010011  10101100  10101101
    		
    		// base编码:https://www.qqxiuzi.cn/bianma/base.php
    		// base32
    		// 11100 10010 11100 01010 11010
    		// 28  18  28  10  26
    		// 4S4K2===
    		
    		// base64
    		// 111001 001011 100010 101101
    		// 57 11 34 45
    		// 5Lit
    		
    	}
    	System.out.println("base32:"+Base32.encode(b1)); // 4S4K2
    	System.out.println("base64:"+Base64.encode(b1)); // 5Lit
    	
 
    	byte[] b2 = "%".getBytes();
    	for(int i=0;i<b2.length;i++) {
    		System.out.println(b2[i]);
    		// 37
    		// 00100101
    		// base32
    		// 00100 10100
    		// 4 20
    		// EU======
    		
    		// base64
    		// 001001 010000
    		// 9 16
    		// JQ==
    	}
    	System.out.println("base32:"+Base32.encode(b2)); // EU
    	System.out.println("base64:"+Base64.encode(b2)); // JQ==
    	
    	
    }
    
	/*
	 * 字符转base62
	 */
    public static void main2(String[] args)  {
    	// base 62
    	String a = "A";
    	byte[] b1 =a.getBytes();
    	for(int i=0;i<b1.length;i++) {
    		System.out.println(b1[i]);
    	}
    	// 65
    	String encode = Base62.encode(a);
    	System.out.println(encode); // 13
    	String decodeStr = Base62.decodeStr(encode);
    	System.out.println(decodeStr); // A
    	
    	String b = "中";
    	byte[] b2 =b.getBytes();
    	for(int i=0;i<b2.length;i++) {
    		System.out.println(b2[i]);
    		// 数字    原码                      反码(原码取反) 补码(反码+1)
    		// -28 00011100  11100011  11100100
    		// -72 01001000  10110111  10111000
    		// -83 01010011  10101100  10101101
    		// 合并
    		// 111001001011100010101101
    		// 转换为62进制
    		// 10TrT
    	}

    	String encode1 = Base62.encode(b);
    	System.out.println(encode1); // 10TrT

    	// 还原为a
    	String decodeStr1 = Base62.decodeStr(encode1);
    	System.out.println(decodeStr1); // 中
    }
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值