【Java Web】将csv文件导入到服务器上的数据库中,出现中文乱码问题

将csv文件导入到服务器上的数据库中,出现中文乱码问题


最近由于需要将之前做的一个Java Web项目部署到服务器上,于是今天开始着手对数据库进行迁移。这里需要提前说明一下我的服务器环境和数据库版本信息:
首先,我的服务器选用的是阿里云的(你懂的,学生优惠嘛),操作系统选择了CentOS 7.3(确实好用)。然后在云主机上,我的数据库使用的是MariaDB(可通过yum命令直接安装:yum install mariadb-server)。
基于这样的一个背景,我将原数据库中的数据以csv的文件格式进行了单独保存(在Windows下),然后再上传到了服务器中。本来我以为只要通过load命令就能将这些数据成功导入数据库中,但是没曾想出现了中文乱码问题。现将这个坑纪录如下,以帮助大家在未来的开发过程中少走弯路,同时也给自己做一个总结。



文章目录

      • 1.在服务器端的数据库中建库与表
      • 2.准备将要导入的csv文件
      • 3.文件上传
      • 4.问题的出现
      • 5.问题的分析与解决


1.在服务器端的数据库中建库与表

首先,转移数据必然涉及到数据库的重建。下面先进入数据库,输入如下指令:
mysql -u[用户名] -p[密码]
其中 [用户名] 是指你在安装数据库时你设置的用户名,通常都是root;
[密码] 是指你安装数据库时设置的密码。
由于我的数据库中用户名和密码都为 root ,故进入数据库的指令为:mysql -uroot -proot 。效果如下:
【Java Web】将csv文件导入到服务器上的数据库中,出现中文乱码问题_第1张图片
接下来是数据库的建立。为了便于大家的理解,这里我就不用我的数据库和数据表了(主要是字段太多,不方便大家理解)。下面我将建立一个用于测试的数据库,假设其名称为 testdb ,则建库代码为:
create database testdb;
建库之后,我们选择使用该库,代码如下:
use testdb;
接下来是建表。这里就以最简单的学生表结构为例来进行原理的阐明(反正大家懂起原理和解决思路就行了,表结构啊,字段什么的无所谓)。现假设表结构如下:

学生id 学生姓名 学生性别
1 张居正
2 上官婉儿
3 许灵均
4 郁可唯
5 苏幕遮

则建表语句如下:

create table student(
id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
sex CHAR(3) NOT NULL,
PRIMARY KEY (id)
);

整个建库、建表的实验效果如下:
【Java Web】将csv文件导入到服务器上的数据库中,出现中文乱码问题_第2张图片




2.准备将要导入的csv文件

1中的工作主要是在服务器上进行的,接下来我们需要在Windows中将我们需要转移的数据全部导出为csv文件。
首先打开你存放数据的Excel文件,然后依次点击“文件” —> “导出” —> “更改文件类型” —> “CSV(逗号分隔)” ,并在弹出的窗体中选择导出文件的存放位置并输入文件名称,如下所示:
【Java Web】将csv文件导入到服务器上的数据库中,出现中文乱码问题_第3张图片
【Java Web】将csv文件导入到服务器上的数据库中,出现中文乱码问题_第4张图片
当你在最后点击“保存”的时候,会弹出一个提示窗口:
【Java Web】将csv文件导入到服务器上的数据库中,出现中文乱码问题_第5张图片
这个直接点击“是”即可,不会影响什么的。
这时,我们就得到了待转移的 student.csv 文件。但是请注意,此时的数据还不能直接用来导入数据库中(无论是本地的MySQL还是云主机上的),因为我们还需要设置其编码(因为Excel默认编码是GBK)。接下来我们找到刚才导出的这个 student.csv 文件,右键选择“用记事本打开”,然后在记事本窗体的最上方选择“格式” —> “字体”,可查看其当前的编码,如下所示:
【Java Web】将csv文件导入到服务器上的数据库中,出现中文乱码问题_第6张图片
显然,这里我们需要对此进行处理(需将编码更改为utf-8)。具体的方法是,点击记事本左上方的 “文件” —> “另存为” ,然后在弹出窗体的最下方 “编码” 项那里,选择编码为 UTF-8,如下所示:
【Java Web】将csv文件导入到服务器上的数据库中,出现中文乱码问题_第7张图片
同时,还需将文件的 “保存类型” 选为 “所有文件” ,并将其名称手动添加后缀 “.csv”,如下所示:
【Java Web】将csv文件导入到服务器上的数据库中,出现中文乱码问题_第8张图片
然后单击保存即可。
至此,我们就成功地得到了可直接用于导入数据库的csv文件(既可在本地用某些可视化工具导入mysql数据库,也可上传到服务器中用命令导入云主机上的数据库)。
在这里有一点需要注意的是,在MySQL的一些可视化工具中(比如HeidiSQL),又或者在是SQL Server中,我们用这种csv文件导入数据到数据库中时,是可以通过设置 “ignore line” 的参数来忽略前 n 项(主要是忽略表头信息,即“学生id”,“学生姓名”,“学生性别”),如下:
【Java Web】将csv文件导入到服务器上的数据库中,出现中文乱码问题_第9张图片
但是在云主机上是没有这些可视化控件来供你选择的,因此在这里我们可以手动的删除带插入表的表头字段的,即:将 student.csv 中的内容手动删除第一行,此时 student.csv 的内容如下:
【Java Web】将csv文件导入到服务器上的数据库中,出现中文乱码问题_第10张图片




3.文件上传

2 中已经得到了可直接导入数据库的csv文件,接下来我们将它上传到服务器中。这里的上传有很多种方式,比如用Linux挂载的方式,或者用文件上传工具 “FileZilla” 或 “Xftp”。这里我用的是 “Xftp” (配套 Xshell 嘛),上传的主要流程如下:

  1. 左侧选择到待上传文件的位置;
  2. 右侧选择待上传文件放在云主机上的位置(这里我放在了 /opt/data 下);
  3. 右键待上传文件,在弹出的菜单中选择 “传输” 即可。

整个过程的截图如下:
【Java Web】将csv文件导入到服务器上的数据库中,出现中文乱码问题_第11张图片
这时,我们回到终端里查看一下文件是否完整传过来了。通过cat命令可直接输出某指定文件的内容,效果如下(我才发现文件名称咋是sutdent.CSV呢?哈哈,英语单词拼错了,这里先用mv指令改一下名,代码为:mv sutdent.CSV student.csv):
【Java Web】将csv文件导入到服务器上的数据库中,出现中文乱码问题_第12张图片




4.问题的出现

即然文件已经成功传过来了,接下来就正式地将其导入到数据库中啦(前面说了那么多主要是为了让大家看清楚我遇到的问题以及解决该问题的背景)。
首先还是通过mysql -uroot -proot命令进入数据库;
然后输入命令use testdb;使用指定数据库;
接下来通过以下代码将指定文件导入数据库中:

load data infile '/opt/data/student.csv' ignore
into table student
character set utf8
fields terminated by ',' 
enclosed by '"' 
lines terminated by '\r\n';

备注:上面的导入代码是绝对正确的。如果你的文件名称或位置和我不一样,则需要修改 /opt/data/student.csv 这一部分;如果你数据库中的表和我不一样,则需要修改 into table student 这一部分中的 “student” ,其余不需要改动。
如果插入的列是部分列,则需要在上述 sql 语句末尾加入指定的插入列,如:

load data infile '/opt/data/student.csv' ignore
into table student
character set utf8
fields terminated by ',' 
enclosed by '"' 
lines terminated by '\r\n'
(name,sex);

以上命令的执行效果如下:
【Java Web】将csv文件导入到服务器上的数据库中,出现中文乱码问题_第13张图片
如果能看到上图中蓝色框部分,就说明导入数据成功~~~
接下来可通过以下语句来对导入的数据进行查看:
select * from student;
执行的效果如下:
【Java Web】将csv文件导入到服务器上的数据库中,出现中文乱码问题_第14张图片
其中的中文全部乱码。




5.问题的分析与解决

此时,我相信很多人和我一样,是懵的。因为导入的 student.csv 文件确实是 utf-8 的编码,并且在插入的 sql 语句中也指定了设置字符集为 utf8 。那么问题出在那儿呢?我在网上找了大量的资料,大部分都是些莫名其妙的回答和毫无作用的建议(有时候真的觉得CSDN里面好多说废话以及好多抄袭的人,这也是为什么我今天要好好总结下这个坑以及其解决办法的原因)。
我们仔细想想,源文件的格式是 UTF-8 ,在数据库中插入的时候也指定了字符集为UTF-8 ,那么最后乱码的原因只可能是数据库本身的编码问题。后来在网上查阅资料发现,实际上MySQL的默认编码就是UTF-8。但是尽管如此,我们在建库时,如果未指定编码方式,MySQL仍有可能会使用其他编码来指定我们所建立的数据库的编码方式,而这个默认的编码方式是什么呢?我们不得而知。因此,接下来我们就需要查看这个默认的编码方式,这个可以通过命令show variables like "%char%";来查看。效果如下:
【Java Web】将csv文件导入到服务器上的数据库中,出现中文乱码问题_第15张图片
在上面的截图中,特别注意到变量 character_set_database 的编码方式为 latin1 ,这是什么意思我们不需要过分关心,只知道它不是utf8就够了:因为它不是 utf8 才导致了将 csv 文件导入数据库中的乱码问题。于是接下来我们就需要将这个变量的编码方式进行更改。网上提供的解决办法是,用命令:set names utf8;
可以对指定变量进行设置,但是我试过了,不行。
正确的解决办法是,对 /etc 下的 my.cnf 进行配置。输入指令:
sudo vim /etc/my.cnf
在打开的文件中添加以下内容:

[client]
default-character-set=utf8
[mysql]
default-character-set=utf8
[mysqld]
character-set-server=utf8		#连接服务的编码

即,效果如下:
【Java Web】将csv文件导入到服务器上的数据库中,出现中文乱码问题_第16张图片

保存退出后,一定要重启一下数据库,同时也重启一下你的服务器。指令如下:

service mysql restart		#重启数据库
reboot now					#重启服务器

如果重启数据库的过程中报错Failed to restart mysql.service: Unit not found.,这个是正常现象(可能是由于设置了开启重启导致的)。
重启服务器后需要再重新连接。

上两步都执行后,此时我们再连接自己的云主机,并进入数据库。此时再通过命令 show variables like "%char%"; 查看编码方式等变量,效果如下:
【Java Web】将csv文件导入到服务器上的数据库中,出现中文乱码问题_第17张图片
发现 character_set_database 变量已经成功地被修改为 “utf8” ,这时候,我们如果直接执行导入语句:

load data infile '/opt/data/student.csv' ignore
into table student
character set utf8
fields terminated by ',' 
enclosed by '"' 
lines terminated by '\r\n';

你会发现结果依然是乱码,如下:
【Java Web】将csv文件导入到服务器上的数据库中,出现中文乱码问题_第18张图片
出现这现象的原因是:虽然当前 character_set_database 变量已经被修改为 “utf8”,但是我们数据库中的当前数据库 testdb 是在该变量修改前就建立的,因此该数据库的编码依然是 latin1 (非utf8)。所以这时你导入任何 csv 文件在 testdb 中都会导致中文乱码。正确的解决办法是:删除当前数据库,并重新建库、表,然后再导入 csv 文件。

下面我们直接删除当前数据库 testdd ,代码为:drop database testdb;
然后再重新建库,代码为:create database testdb;
并使用该数据库,代码为:use testdb;
接着新建student表,代码为:

create table student(
id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
sex CHAR(3) NOT NULL,
PRIMARY KEY (id)
);

最后,再次导入 student.csv 文件到 student 表中,代码为:

load data infile '/opt/data/student.csv' ignore
into table student
character set utf8
fields terminated by ',' 
enclosed by '"' 
lines terminated by '\r\n';

此时,我们再次执行查询语句 select * from student; ,效果如下:
【Java Web】将csv文件导入到服务器上的数据库中,出现中文乱码问题_第19张图片
发现所有的中文均能正确显示。




你可能感兴趣的:(Java,Web,学习之路,数据库中文乱码问题,如何将csv文件导入数据库,csv文件的编码问题,数据库的编码问题,数据库的默认编码)