在编码的江湖中,"乱码"算得上我们遇到的最难缠的"敌人"之一,一旦遇上、轻则心情烦躁、重则心态崩溃。文章开头,让我们再次重温与"乱码"初见面的名场面。
String str = "乱码,你好";
byte[] bytes = str.getBytes("GBK");
String string = new String(bytes,"UTF-8");
System.out.println(string);
运行结果:
是不是感觉很熟悉,这个是出现乱码最简单的例子,虽然在编程时我们肯定不会这样写,但是,乱码出现的原因都是相通的,想要知道为什么?那就继续我们的"乱码"江湖的闯荡吧。
想要从根本上铲除"乱码"这个敌人,我们就必须对它的生命历程有清楚的认识,正所谓:"知己知彼,才能百战不殆"。
(一)"乱码"产生的原因:
在编码江湖中,我们想要生存下来,首先得懂得这个江湖的规则,计算机就是我们闯荡的编码江湖,但是,计算机的规则约定: 它们只能够读懂二进制数0和1,我们能够表达的确实对应的字符,为了在编码程序中生存下来,我们需要一种技术能够将我们表达的字符转换成对应计算机能够读懂的二进制数0和1,这种技术就叫编码。
但是,因为闯荡这者的不同,所表达的字符就存在差异,所以针对不同的闯荡地区,存在不同的编码,如果不是同一个地区使用了其他地区的编码方式进行转换,就会出现"乱码",计算机就会看不懂。
想要在计算机世界行走江湖,就必须对这个世界的基础概念有个清晰的认识,下面就讲解关于计算机世界的基础知识讲解:
计算机世界的最小存储单位,也是计算机能够读懂的,可取的值是0或1,每个值就标识1位,如:0000 0001表示的就是8位,转换成我们认识的数值(十进制)就是1。
计算机世界中的一种表示存储容量的单位,1Byte = 8Bit,即一个字节可以存储8位,除了Byte外,计算机还有以下常用的存储容量单位以及他们之间的转换关系:
1Byte = 8bit
1KB(KByte) = 1024Byte = (1024 * 8)bit
1MB(MByte) = 1024KB =(1024 * 1024)Byte = (1024 * 1024 * 8)bit
1GB = 1024MB = (1024 * 1024)KB =(1024 * 1024 * 1024)Byte = (1024 * 1024 * 8)bit
1T = 1024GB = (1024 * 1024)MB = (1024 * 1024 * 1024)KB =(1024 * 1024 * 1024 * 1024)Byte = (1024 * 1024 * 1024 * 8)bit
字符也就是我们在计算机表达的"语言",常见的包括:数值、字母、文字和符号,如:1、a、A、试、$...都表示的是一个字符,在计算机世界中,不同的字符可能需要不同的存储容量进行存储。
集:表示集合,字符集则表示多个字符的集合,每个字符集可以包括不同的字符,常见的字符集如下:
ASCII字符集
GB2312字符集
Unicode字符集
定义: 将字符集中的字符编码(映射)成集合中的某一个对象如:比特模式、自然数序列、电脉冲等,以方便字符在计算机中存储和在计算机网络中传递
字符集表示:多个字符的集合,字符编码则是:将字符集中的字符映射为特定的字节或者字节序列,它表示的是一种规则。通常特定的字符集采用特定的编码方式(即一种字符集对应一种字符编码,如: ASCII、ISO-8859-1、GB2312、GBK都是表示了字符集又表示了对应的字符编码,但Unicode字符集是特例,它对应的字符编码有:UTF-8、UTF-16、UTF-32)
1、打开控制台(win+R),输入cmd回车
2、右键菜单栏选择属性
3、当前代码页就是对应的字符集编码
计算机的世界中,它只能懂得0和1(即二进制),但是,我们交流的时候是通过字符进行交流,所以,如果想要计算机了解我们想表达的东西,以及我们想了解计算机想表达的东西,就需要在字符和0与1之间进行转换,也就是: 编码和解码
就编码和解码而言,针对的是我们(即在计算机中闯荡的人),这样就不会混淆这两个概念。
编码: 将字符按照对应的编码类型转换成计算机能够识别的0或者1(类似于生活中的:将中文翻译成英文的翻译官)
解码: 将0和1根据对应的解码类型转换成我们能够读懂的字符(类似于生活中的: 将英文翻译成中文的翻译官)
ASCII、GB2312、Unicode、GBK等
ASCII字符集: 全称《美国信息交换标准代码》,主要用于显示现代英语和其它西欧语言,主要包括:可显示字符(英文字母、阿拉伯数值、标点符号)、以及控制字符(回车、换行、退格等特殊字符)。
ASCII编码: 美国定制的交换标准,目的是将ASCII字符集包含的字符转换成计算机能够识别的二进制(0和1),它是最通用的信息交换标准,到目前为止总共定义了128个字符。
ASCII编码缺点: 只能显示26个基本拉丁字母、阿拉伯数目字和英式标点符号,因此只能用于显示现代美国英语(而且在处理英语当中的外来词如naïve、café、élite等等时,所有重音符号都不得不去掉,即使这样做会违反拼写规则),而且对其他的语言支持力度也不大,所以现在苹果也使用Unicode替换ASCII。
(1) GB2312字符集:
(2)GBK字符集
(3)GB18030字符集
(1) UTF-8字符编码:
(2) UTF-16字符编码:
(3) UTF-32字符编码:
通过上面的基础规则学习,我们已经对字符集、编码、解码等基础知识有了基本的认识。现在我们就通过图形化来举一个例子更加形象理解的这些知识(以:ASCII字符集为准,用我们编程入门的最常见的字符串:hello world为例子)
编码: 在屏幕输入文字 -> 根据指定编码类型 -> 将输入的文字编码成计算机能够识别的二进制数 -> 计算机存储编辑成的二进制数值
解码: 计算机读取存储的二进制数值 -> 根据指定的解码类型解码 -> 将二进制数值解码成字符集中表达的字符 -> 在屏幕显示
通过上面的例子,我们能够更加清楚编码和解码的过程。同时,也看出了乱码出现的原因:
知道出现乱码的两个原因,要解决乱码就要同时满足以下两个条件:
1. 编码过程和解码过程使用同一种编码方式
2. 使用支持需要编码解码的字符串对应的字符集
File -> setting -> 输入File encoding -> 设置成对应的字符集
通过控制台登录到mysql后。
show variables like 'character_set%'
//当前会话,退出控制台后又恢复回原来默认的编码方式
set character_set_server=utf8;
set character_set_database=utf8;
//全集范围,无论是否退出控制台,以后都是使用这个编码方式
set global character_set_database=utf8;
set global character_set_server=utf8;
1、w3c网站-字符集和字符编码(Charset & Encoding)
2、乱码的产生和解决
不积跬步,无以至千里;不积小流,无以成江海。今天播种努力的种子,总会有一天发芽!