Java 与 Mysql 的乱码问题总结 + Msql 字符串排序

前言

  乱码问题已经遇到过好几次了,都是依靠搜索引擎碰运气解决问题,今天正好空下来,把以前搜集的几篇博客好好看了一下,对于乱码问题有点拨开云雾见青天的感觉。

  这篇随笔只是个人用来做个小笔记的,写的不会很清楚,要想知道细节的强烈推荐看下面这两篇博客:

  MySQL字符集与排序规则总结

       常见乱码问题分析和总结

文件乱码原因概述

  1. 缺少字体库

    表现:出现字符用方框表示

    解决:安装合适的字体库

  2. 编码问题

    表现:用问号表示字符

    解决:编码的时候设置编码集,在Java中,一般是输出的时候使用的是字节流(FileOutPutStream)而不是字符流(Writter)

  3. 解码问题

    表现:出现奇怪的字符串

    解决:解码的时候,用Reader进行解码,并设置编码集(默认会依赖JVM的系统环境,默认是 file.encoding 属性)

WEB乱码原因概述

  1. Post 请求,不论是浏览器端还是服务器点,解码编码格式都由 Header中的 ContentType(“text/html; charset=utf-8″) 指定,所以只要不漏写,都不会有问题。

   唯一的风险在于请求发送过程中,中间的代理器会不会修改这个值(一般不会有人去改)。

  2. GET 请求,get 请求的URL 中的 PathInfo 和 QueryString 字符串的编码和解码是由浏览器和应用服务器的配置决定(Tomcat 服务器一般在 server.xml 中设定的,pathInfo 部分进行解码的字符集是在 connector 的 中定义的;QueryString 的解码字符集一般通过 useBodyEncodingForURI 设定,如果没有设定,Tomcat8 之前的版本默认使用的是 ISO-8859-1,但是 Tomcat 8 默认使用的是 UTF-8),所以在我们的程序中最好不要在 URL 中直接使用非 ASCII 字符,如果一定要用,就用 encodeURI() 进行编码。

  3. Header 只支持 ASCII 字符集,将不在 ASCII 字符集内中的其他字符全部编码为 3F 即问号?,解决办法就是对中文文件名使用 url 编码后 URLEncoder.encode(filename,charset)再放到 Header 中。

protected void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
    String fileName = getDecodeParameter(request,"fileName");
    String userName = getDecodeParameter(request, "username");
    response.setHeader("Content-Disposition", "attachment; filename=\"" +
    URLEncoder.encode(fileName,"utf-8") + "\";userName=\"" +
    URLEncoder.encode(userName,"utf-8") + "\"");
}

  另一种Header乱码处理思路,文件名用ASCII格式编码(这种方式需要浏览器支持,如果使用postman调试依旧是乱码):

// 采用中文文件名需要在此处转码, 因为 Header 固定采用ASCII格式编码
response.setHeader("Content-Disposition","attachment;filename=" + MimeUtility.encodeWord(biFile.getName()));

 

MYSQL乱码原因概述

  1. 数据库各层级间的编码格式不一致,需要转换代码格式,然后出错

    排查方向:用问号代替字符

    排查与修复可能使用的SQL:

# MySQL的系统变量(字符集相关的系统变量)
show variables like 'character_set%';
# 查看当前MySQL版本支持的字符集
show charset;
show character set;
# 查看MySQL数据库的字符集
show variables like 'character_set_database';
show create database dbname;  #--dbname为你要查看的数据库。
#查看MySQL表的字符集
show create table xxxx;

## ---------- 修改字符集
# 1:修改MySQL字段的字符集
# 修改字段的字符集语法如下所示,当然,成功的修改字符集是有限制的,具体参考10.1.7 Column Character Set Conversion,修改前最好做好备份,充分测试。
ALTER TABLE xxx MODIFY xxx VARCHAR(50) CHARACTER SET UTF8;
# 2. 修改MySQL表的字符集
alter table class charset=gbk;
alter table class character set UTF8mb4;
#注意:上面命令只修改表的字符集,影响后续该表新增列的默认定义,已有列的字符集不受影响。
#同时修改表字符集和已有列字符集,并将已有数据进行字符集编码转换。可以使用类似下面脚本。
alter table class convert to character set UTF8mb4;
# 3. 修改MySQL数据库字符集
# 注意:只修改库的字符集,影响后续创建的表的默认定义;对于已创建的表的字符集不受影响。
alter database database_name character set xxx;
# 4:修改系统变量character_set_database
set character_set_database=utf8mb4;
set global character_set_database=utf8mb4;
# 5:修改MySQL服务器字符集
set global character_set_server=utf8mb4;
# 6. 另外,SET NAMES 'charset_name' [COLLATE 'collation_name'] 相当于SET character_set_client = charset_name; SET character_set_results = charset_name; SET character_set_connection = charset_name;
set names 'utf8mb4';

 

  2. 输入的字符当前编码格式不支持,例如 mojo 表情和复杂繁体中文,需要使用 UTF8mb4

    表现:字符不对应,例如应该是表情,展示的却是繁体字

    修复:同上

MySLQ排序规则特征:

  两个不同的字符集不能有相同的校对规则;

  每个字符集有一个默认校对规则;

  存在校对规则命名约定:以其相关的字符集名开始,中间包括一个语言名,并且以_ci(大小写不敏感)、_cs(大小写敏感)或_bin(二元)结束。

 

 

 

posted @ 2020-12-03 17:22  上课爱睡觉  阅读(208)  评论(0)    收藏  举报