PHPMYSQL之——字符编码,乱码,set names的意思

2023-10-30 21:50

本文主要是介绍PHPMYSQL之——字符编码,乱码,set names的意思,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、字符编码简介

      计算机里,只能用二进制码记录文字、图片、图像、声音等媒体,要想将各式各样的媒体映射为简单的二进制编码(媒体 –> 01),就要将很多01根据多种变化的排列组合来表示这些媒体,这些排列组合的方法就成为了编码,文字、图片、声音都存在各式各样的编码。今天学习一下燕十八PHP公益培训课之——字符编码篇。

       1、ASCII

最早的编码——ASCII编码,ASCII编码只能表示键盘上(A-Z、a-z、0-9、+-*/&^%)等不超过127个字符。

1个字节有8位,可以表示256个字符,要表示ASCII码只需要7位就够了,所有最高位始终是0。

0000 0000
1111 1111    -->   共256种值

常用汉字3000多,1个字节不能表示,只能用2个字节表示,可以表示65535个字符,表示汉字够用了。

0000 0000 0000 0000
1111 1111 1111 1111  -->  共65535种值
      2、GB2312

最早的中文字符集GB2312,GB2312不占用ASCII的0-127,两个字节组合来用,但是这样的组合就少了很多,例如:

1xxx xxxx 1xxx xxxx  -->  [129 - 255] [129 - 255]
例如:
130  140     97       95      144 233   (分组前)
↓          ↓         ↓           ↓
[130 140]  [97]     [95]    [144 233]   (分组后)
↓          ↓         ↓           ↓
[汉字]    [字母]   [字母]    [汉字]

GB2312只收录了6763个汉字,基本满足了常用汉字的需求,但有些汉字没有收录。

     3、GBK

GBK编码完全兼容GB2312,GBK还是双字节,理论上第2字节不再局限于129-255,如果第1字节大于128,则带下一个字节组成一个汉字,如果第1个小于128,就直接转ASCII。例如:

1xxx xxxx xxxx xxxx  -->   [129 - 255][0 - 255]
例如:
133  22    63      199  22     (分组前)
↓         ↓           ↓
[133 22]  [63]    [199 22]    (分组后)
↓         ↓           ↓
[汉字]   [字母]     [汉字]

实际上,GBK的编码方式,有单字节和双字节编码组成,00-7F范围内只占一位,和ASCII保持一致,此范围内阉割上说有96个字符和32个控制符号。之后的双字节中,前一字节是双字节的第一位。总体上说第一字节的范围是81-FE(也就是不含80和FF),第二字节的一部分领域在40-7E,其他领域在80-FE。收录汉字21003个、符号883个、并提供1894个造字码位。

      4、Unicode和UTF-8

Unicode是一个世界通用的码表,它占4个字节,包含232,共40多亿字符,但常用的集中在前65535个标号里,2个字节就够用了。Unicode只负责分配编号,而且都用4个字节来分配编号,而真正的实现方式成为Unicode转换格式(Unicode Transformation Format,简称为UTF)

例如,如果一个仅包含基本7位ASCII字符的Unicode文件,如果每个字符都使用2字节的原Unicode编码传输,其第一字节的8位始终为0,这造成了较大的浪费。对于这种情况,可以使用UTF-8编码,这是一种变长编码。它根据一定的算法减小浪费,具体实现如下:

Unicode根据一定算法转为UTF-8
例如:
0000 0000 0000 0000 0000 0000 0000 0041 –> A    (Unicode)

0000 0041 –> A                                                 (UTF-8)

Unicode与UTF-8的关系就像原文件与压缩文件的关系,具体如下:

UCS-4编码

UTF-8字节流

U+00000000 - U+0000007F 0xxxxxxx
U+00000080 - U+000007FF 110xxxxx 10xxxxxx
U+00000800 - U+0000FFFF 1110xxxx 10xxxxxx 10xxxxxx
U+00010000 - U+001FFFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
U+00200000 - U+03FFFFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
U+00040000 - U+7FFFFFFF 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

UTF-8编码是根据第一字节的高位来决定一个字符占几个字节的,基本规律是:

第一字节高位

占用字节数

0 1个字节
11 2个字节
111 3个字节
1111 4个字节
11111 5个字节
111111 6个字节
二、乱码的形成

乱码产生的原因:

  • 解码时与实际编码不一致(可修复)。
  • 传输过程中,编码不一致,导致字节丢失(不可修复)。

1、解码时与实际编码不一致情况

复制代码
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
  <!--  当charset为utf-8时,文档又另存为ansi(GBK)格式,网页就会产生乱码  -->!-- --》
  <title>乱码测试</title></head><body>测试</body>
</html>
复制代码

2、传输过程中,编码不一致,导致字节丢失

大二

MySQL乱码形成和字符集设置。

MySQL的字符集转换过程如下图:

image

这个过程至少存在3个字符集的设置,客户端字符集、连接器字符集、服务器端字符集。其中连接器起到至关重要的作用,具体流程为,客户端向服务器端存数据时,客户端将自身字符集编码的数据发送到连接器,连接器选择一种字符集进行转换,然后再将转换好的字符集转换为服务端字符集,再发送给服务器端存储。当客户端向服务器端取数据时,以上过程相逆。

下图为一种场景:

image

客户端为GBK编码,连接器为UTF8编码,服务器端也为UTF8编码。当客户端将GBK编码的数据发送到连接器时,连接器将GBK编码的数据转换为UTF8编码,暂存在连接器,之后连接器再将暂存的数据不进行任何转换发送到服务端存入数据库。客户端取数据时,将上述过程相逆。

这样场景可能存在一定的问题,如果数据库中本来就存储了只有UTF8编码下才有而GBK编码下没有的字符,在客户端取数据时,由连接器UTF8编码的字符再转换为GBK时就可能丢失字节。(如果场景只针对中国,可能不会存在什么问题。)

 

下图是另一种场景

image

客户端还是GBK编码,连接器也是GBK编码,服务端还是UTF8编码。当客户端将GBK编码的数据发送到连接器是,连接器不进行转换,暂存在连接器,连接器再将暂存的GBK编码的数据转为UTF8编码发送到服务器。取数据时与上述过程相逆。这个场景也会出现丢失字节的现象。

 

根据以上场景分析,若想在MySQL不出现乱码,需要指定客户端的编码,让连接器不理解错误,这样就不会存入错误的数据,取数据的时候,要告诉连接器,返回结果的字符集,所以要设置3个字符集分别是:客户端字符集、返回结果字符集、连接器字符集。

看以下场景

复制代码
#设置客户端字符集为GBK
set character_set_client=gbk;#设置连接器字符集为GBK
set character_set_connection=latin1;#设置返回结果字符集为GBK
set character_set_results=gbk;
复制代码

当客户端为GBK,连接器为latin1时,客户端字符集的容量比连接器的字符集的容量大,比如客户端包含中文汉字编码,但连接器却没有,当客户端有汉字数据发送到连接器时,连接器转为latin1时将丢失字节,就会产生乱码,而且这种乱码是不可修复的字节码丢失(上一篇 乱码的第2种情况)。

总结上面,Server字符集 >= Connection字符集 >= Client字符集。

set character_set_client=gbk;
set character_set_connection=gbk;
set character_set_results=gbk;#以上三条都设置为gbk,可以简写为以下形式
set namesgbk; ;

总结上一篇和本文,要想php+mysql开发中不出现乱码需注意以下几点:

  1. html、php的meta中的charset信息的编码
  2. html、php等文件保存的编码格式
  3. mysql数据库中client、connection、results
  4. mysql数据库表字段编码

以上四点编码都统一

这篇关于PHPMYSQL之——字符编码,乱码,set names的意思的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/310800

相关文章

MySQL中FIND_IN_SET函数与INSTR函数用法解析

《MySQL中FIND_IN_SET函数与INSTR函数用法解析》:本文主要介绍MySQL中FIND_IN_SET函数与INSTR函数用法解析,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一... 目录一、功能定义与语法1、FIND_IN_SET函数2、INSTR函数二、本质区别对比三、实际场景案例分

Python使用自带的base64库进行base64编码和解码

《Python使用自带的base64库进行base64编码和解码》在Python中,处理数据的编码和解码是数据传输和存储中非常普遍的需求,其中,Base64是一种常用的编码方案,本文我将详细介绍如何使... 目录引言使用python的base64库进行编码和解码编码函数解码函数Base64编码的应用场景注意

如何解决Spring MVC中响应乱码问题

《如何解决SpringMVC中响应乱码问题》:本文主要介绍如何解决SpringMVC中响应乱码问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Spring MVC最新响应中乱码解决方式以前的解决办法这是比较通用的一种方法总结Spring MVC最新响应中乱码解

Nginx指令add_header和proxy_set_header的区别及说明

《Nginx指令add_header和proxy_set_header的区别及说明》:本文主要介绍Nginx指令add_header和proxy_set_header的区别及说明,具有很好的参考价... 目录Nginx指令add_header和proxy_set_header区别如何理解反向代理?proxy

解决Java中基于GeoTools的Shapefile读取乱码的问题

《解决Java中基于GeoTools的Shapefile读取乱码的问题》本文主要讨论了在使用Java编程语言进行地理信息数据解析时遇到的Shapefile属性信息乱码问题,以及根据不同的编码设置进行属... 目录前言1、Shapefile属性字段编码的情况:一、Shp文件常见的字符集编码1、System编码

Java程序运行时出现乱码问题的排查与解决方法

《Java程序运行时出现乱码问题的排查与解决方法》本文主要介绍了Java程序运行时出现乱码问题的排查与解决方法,包括检查Java源文件编码、检查编译时的编码设置、检查运行时的编码设置、检查命令提示符的... 目录一、检查 Java 源文件编码二、检查编译时的编码设置三、检查运行时的编码设置四、检查命令提示符

C语言字符函数和字符串函数示例详解

《C语言字符函数和字符串函数示例详解》本文详细介绍了C语言中字符分类函数、字符转换函数及字符串操作函数的使用方法,并通过示例代码展示了如何实现这些功能,通过这些内容,读者可以深入理解并掌握C语言中的字... 目录一、字符分类函数二、字符转换函数三、strlen的使用和模拟实现3.1strlen函数3.2st

VSCode中C/C++编码乱码问题的两种解决方法

《VSCode中C/C++编码乱码问题的两种解决方法》在中国地区,Windows系统中的cmd和PowerShell默认编码是GBK,但VSCode默认使用UTF-8编码,这种编码不一致会导致在VSC... 目录问题方法一:通过 Code Runner 插件调整编码配置步骤方法二:在 PowerShell

基于.NET编写工具类解决JSON乱码问题

《基于.NET编写工具类解决JSON乱码问题》在开发过程中,我们经常会遇到JSON数据处理的问题,尤其是在数据传输和解析过程中,很容易出现编码错误导致的乱码问题,下面我们就来编写一个.NET工具类来解... 目录问题背景核心原理工具类实现使用示例总结在开发过程中,我们经常会遇到jsON数据处理的问题,尤其是

Python如何实现读取csv文件时忽略文件的编码格式

《Python如何实现读取csv文件时忽略文件的编码格式》我们再日常读取csv文件的时候经常会发现csv文件的格式有多种,所以这篇文章为大家介绍了Python如何实现读取csv文件时忽略文件的编码格式... 目录1、背景介绍2、库的安装3、核心代码4、完整代码1、背景介绍我们再日常读取csv文件的时候经常