数据库系统开发中字符编码问题的研究

2013-01-29 05:52张鹏伟李建文
陕西科技大学学报 2013年5期
关键词:日文数据库系统后台

张鹏伟, 李建文

(陕西科技大学 电气与信息工程学院, 陕西 西安 710021)

0 引言

数据库系统的安全问题是数据库开发中重要考核指标之一,但目前在我国由于字符编码的混用,数据库系统普遍存在着安全隐患.数据库系统开发的主要任务是对文本字符进行输入、检索、输出,整个过程都离不开处理字符串的问题[1].随着信息全球化的发展,现在的字符串已经进入多种字符编码混用的时代[2-5].事实上,现在的大部分软件开发工具都提供字符编码的选择功能,但由于人们对于字符编码知识的缺失而忽视了字符编码的正确选择,以致于造成了实际应用过程中的安全隐患.

图1是Windows XP “记事本”中“另存为”时可选择字符编码的界面,里面出现了3种字符编码,即ANSI、Unicode、UTF-8等,事实上还有ASCII、ISO8859等.我们只有搞清楚了它们之间的理论关系,才能开发出可靠的数据库系统.

图1 Windows XP “记事本”中“另存为”选择字符编码

1 ANSI、Unicode与UTF-8

1.1 ANSI的介绍

ANSI (American National Standards Institute)编码就是将原来的ASCII字符扩充为256个,如图2所示.后面的128个(0x80-0xFF)由其他国家用来构造本国文字编码.其中简体汉字、中文BIG5、日文汉字、韩文都特别多,需要2个ANSI字符才能拼成一个字符.

图2 ASCII与ANSI字符集关系

Oracle数据库的默认编码方式为ISO8859-1[6],即ASCII.ISO8859基本特点是:(1)与 ASCII 兼容;(2)码位0x80-0x9F (或 128-159),保留给扩充定义的 32 个控制码,称为 C1控制码 (0-31 称为C0控制码);(3)每个字符集定义至多 95 个字符,其码位都在 0xA1-0xFF(或 161-255).我国GB2312-80规定一个汉字由两个扩充ASCII码0x80-0x9F拼成,所以汉字最多94*94个,仅适用于简体汉字.

这样虽然解决了各国文字使用计算机的问题,但随着信息全球化的发展,人们又需要在同一台计算机、同一个操作系统、同一套软件内容等中同时使用很多国家的文字.这便需要将全世界所有的字符进行统一编码,这就是Unicode.

1.2 Unicode简介

通常所说的Unicode是UTF-16编码[2,3].Unicode工作开始于1991年.UTF-16字符字节数统一为2字节,16位,字符编码范围0-65535.其中,日文编码0x3400-0x4DC0;中文汉字编码0x4E00-0x9FC0,不分简体与繁体;韩文编码0x3AC00-0x3D7C0.在原来的ANSI中,常用汉字以拼音为序,但在UTF-16中所有汉字以偏旁部首为序.

通常情况下,编码中的Unicode是指UTF-16,见图1.Unicode big endian是将Unicode的2个字节进行了位置交换,仍然是UTF-16.由于UTF-16编码中所有字符都是2个字节,使得UTF-16编码在存贮和字符检索时很方便.但UTF-16编码也有缺点,主要是关于英文字符的编码与ASCII不一致.在UTF-16中英文字符是2个字节,在ASCII中英文字符是1个字节,尽管顺序完全一样,在UTF-16中英文字符的高8位总为0.因此,UTF-16中在网络上传输英文字符效率比ASCII低.事实上不仅仅是传送英文字符文本,而且HTML中全部使用英文字符做传输指令的,即使传送的全部是汉字文本,但仍然少不了HTML语言指令.在这样的背景下,就诞生了UTF-8.

1.3 UTF-8编码规则

UTF-8是一种不定长的字符编码,可以看做是UTF-16的变种.UTF-8来源于UTF-16,但改变了UTF-16中所有字符字节数都是2的特征.UTF-8与UTF-16字符数一样多,而且顺序都一样,UTF-8中分为1、2和3字节字符.UTF-16中字符编码是连续的,由0到65535,按照16进制就是0到FFFF.而UTF-8中字符编码整体不连续,但分段连续,UTF-8的分段与UTF-16对应关系如表1所示.

表1 UTF-8的分段与UTF-16对应关系(16进制)

2 3种字符编码的优缺点

事实上,3种字符编码各有优缺点,现在都常用.其中ANSI仍然用于数据库中,UTF-16是Unicode的标准,OFFICE Word内部完全使用UTF-16,UTF-8主要用于网页传送.

Windows操作系统为人们使用这3种字符编码创造了良好的环境,以致于人们没有感觉到字符编码已经发生了重大变化.这是由于平常我们对字符串进行操作时,Windows为我们进行了自动的转换服务,特别是进行字符串的“COPY”过程.但是,我们必须知道以下3点:

(1)UTF-16与UTF-8字符串进行转换时可以完全转换,仅仅可以出现存贮空间上的差异,因为UTF-16的字符一律2字节,而UTF-8中英文字符占1个字节,一个汉字占用3个字节.

(2)ANSI字符转换为Unicode字符时可以完全转换,因为对于每个指定的国家而言ANSI字符集仅仅是Unicode字符集的子集,可以向上映射但不能建立一一对应映射.

(3)Unicode字符转换为ANSI字符往往是无法进行的,因为对于每个指定的国家而言ANSI字符集简直太小了.

3 数据库系统的前台与后台

数据库系统一般由用户界面和后台操作两大部分组成,见图3.用户界面属于前台,主要照顾到方便、美观,往往与流行的编程工具和网络环境关系极为密贴;数据库属于后台,主要照顾到可靠性和对于历史数据的兼容性.往往数据库系统的前台和后台所使用的字符编码可能不一致.

用户操作主要分为两种,即数据录入和数据查询.数据录入过程主要由用户界面的数据录入模块实现,具体的操作可能是键盘输入,或者由其它文字块拷贝实现.数据录入后经保存后写入后台数据库,这时如果前台和后台编码不一致就必须经过“前台=>后台编码转换”.这个转换过程由操作系统自动完成,操作者感觉不到.

数据查询就是读取数据库中的数据,并显示在用户界面中.相对于数据录入来说,数据查询更为频繁,也可以说,数据录入的目的就是为了数据查询.如果前台和后台编码不一致,在读取数据库数据后,就必须经过“后台=>前台编码转换”[7].这个转换过程也由操作系统自动完成,一般情况下操作者感觉不到,除非经过特殊的构思才能发现问题.

图3 数据库前台后台编码转换示意图

在字符录入过程,由于使用了先进的UTF-8,不会丢失任何字符.再写入后台时,由于两个字符编码不一致会导致Unicode字符丢失.在查询时又要发生一次字符编码转换,但这时是ANSI转为Unicode,也不会发生字符丢失.在显示字符时才发现字符丢失,但不是发生在显示过程,而是发生在保存数据的过程.

4 数据库系统中的数据丢失问题及解决办法

4.1 数据丢失实例

如图4、图5所示,为基于J2EE的油田物资管理信息系统开发过程中出现的中文乱码和数据丢失问题.在图4中,由另一个包涵全部Unicode字符的文件中复制了一些日文汉字、日文符号和韩文,粘贴到键盘输入框内,可以看到这些日文汉字、日文符号和韩文都可以出现.但经过“保存”后再查询时便出现如图5的情况,日文汉字、日文符号和韩文全部变成“???????”,这就是数据丢失现象.

图4 数据录入界面

图5 数据查询界面

4.2 数据丢失原因分析

根据字符编码理论,这属于典型的系统表现层、应用层和数据层编码不一致造成的结果.经过仔细核对数据库编码方式,该系统使用了Oracle数据库,编码方式采用默认的ISO8859-1编码方式.系统应用层开发采用J2EE技术框架,字符编码选择了UTF-8.而客户端浏览器采用中文操作系统默认的gb2312字符集.J2EE程序在编写、编译、输入、输出过程中采用的字符编码不一致,导致了中文乱码的产生或系统数据的丢失[8,9].ISO8859-1中仅能容纳的文字和符号最多8 000多个.Unicode中有全部的汉字、日文汉字、韩文和符号,共六万多个.数据丢失发生在“保存”过程,绝大部分Unicode字符在转换为ISO8859-1时都会被丢失,但常用的简体汉字却不会丢失.这正是为什么丢失字符的现象反而不容易被人们发现的原因.

4.3 解决方法

解决上述数据丢失和中文乱码问题的根本办法,就是明确指定整个应用系统使用统一的字符编码集.指定统一字符集时,到底是采用ISO8859-1 、GBK还是UTF-8字符集呢?

(1)如果统一指定为ISO8859-1,运行操作系统的默认编码必须是ISO8859-1,如Linux.因为目前大多数软件都是西方人编制的,他们默认的字符集就是ISO8859-1,包括操作系统Linux和数据库MySQL等.然后需要将开发和编译Java代码[10]时的字符集指定为ISO8859-1,在JSP页面的头部增加字符编码集的声明.

(2)如果统一指定为GBK中文字符集,则系统只能运行在默认编码为GBK的操作系统,如中文Windows.其它设置同上.统一编码为ISO8859-1和GBK虽然带来编制代码的方便,但是各自只能在相应的操作系统上运行,这也破坏了Java跨平台运行的优越性,只在一定范围内行得通.例如,为了使得GBK编码在Linux上运行,设置Linux编码为GBK.

(3)将系统的编码统一定义为UTF-8,这是一种除了应用系统以外不需要进行任何附加设置的中文编码正常显示的根本解决方案.UTF-8编码是一种兼容所有语言的编码方式,唯一比较麻烦的就是要找到应用系统的所有出入口,然后将其编码方式设置成UTF-8.具体操作方法包括以下几步:

①开发和编译Java代码时指定字符集为UTF-8,可以在开发工具JBuilder或MyEclipse的项目属性中进行设置.

②使用Servlet规范中的过滤器Filter统一指定编码,使所有请求都经过一个Servlet控制器进行分发,通过Servlet的Filter方法进行过滤,将所有来自浏览器的请求(Request)中数据的字符编码转换为UTF-8,因为浏览器发过来的请求包根据浏览器所在的操作系统编码可能是各种形式编码.

③在所有JSP页面头部进行字符编码集的声明:

<%@ page contentType="text/html;charset=GBK"%>.

④在所有的html代码中,声明其字符编码集为UTF-8,将浏览器的编码方式设为UTF-8.

⑤在数据库连接方式中设定数据库字符编码集为UTF-8.例如,连接MYSQL时配置URL如下:jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8,一般数据库都可以通过配置工具设置默认的字符编码集为UTF-8.

⑥其他和外界交互时能够设定编码的都统一设定其编码集为UTF-8,例如读取文件、操作XML文件等.

采用上述方法指定整个J2EE应用系统使用统一的UTF-8字符编码集,可有效地解决Java/J2EE程序的中文乱码问题,除了应用系统以外不需要进行任何附加设置,世界各国的文字便能正常显示,符合了Java程序跨平台的特性和国际化的需求.而且UTF-8是一种不定长的字符编码,英文字符和HTML指令的网络传送效率较高.其缺点是UTF-8编码需要字节数长短不一致,搜索算法复杂,数据占用较大的存储空间.

5 结论

信息全球化使得多种字符编码混用是必然的,同时会产生很多意想不到的问题.忽视字符编码理论会导致数据库系统出现严重的安全隐患[11].

最早的数据库系统内部使用ANSI或ISO8859-1编码,虽然目前主流的数据库系统都兼容了Unicode,但大多默认采用ISO8859-1字符编码,不同编码之间转换时可能引起字符丢失.

在设计数据库系统时,应该尽量使用先进的Unicode,以提高字符兼容性.同时应充分掌握这3种常用的字符编码理论,有效地使用字符编码知识,提高数据库系统的网络数据传送效率,并充分利用存贮空间.

[1] 许 成,李茂青.Unicode数据仓库ETL的设计与实现[J].计算机工程,2008,34(11):74-76.

[2] 李建文,张成现.实用网络通信编程技术[M].北京:北京邮电大学出版社,2006:25-56.

[3] 童天添.基于C#的字符编码映射系统[J].陕西科技大学学报(自然科学版),2010,28(4):96-99.

[4] 维尼拉·木沙江,吐尔地·托合提,吐尔洪·吾司曼.基于重定位的维、哈、柯文Unicode编码及多文种索引技术研究[J].郑州大学学报(理学版),2009,41(1):48-55.

[5] 吴道荣,王善发.获取Unicode字符集中汉字的拼音和内码[J].现代电子技术,2009,32(16):83-85.

[6] 唐小新.基于Unicode字符集数据迁移的设计与实现[J].企业科技与发展,2011(17):22-24.

[7] 包竹苇,李 淼,张 建.Java网络传输中字符编码问题的研究[J].计算机工程与应用,2007,43(4):93-95.

[8] 范道尔吉,白凤山,武慧娟.基于Unicode编码的蒙古文输入法研究[J].中文信息学报,2010,24(6):120-124,128.

[9] 李培峰,朱巧明,钱培德.一个基于ISO/IEC10646的汉字输入模型[J].中文信息学报,2006,20(5):91-96.

[10] 费玉奎.基于Servlet的汉字信息处理方法[J].计算机工程,2000,26(10):173.

[11] 黄鹤鸣,赵晨星.藏文字符集基本集的修订方案[J].计算机工程与应用,2007,43(20):187-189,193.

猜你喜欢
日文数据库系统后台
Wu Fenghua:Yueju Opera Artist
后台暗恋
作为证据的足跡(mör)与它的证明力一以卫拉特法为中心(日文)
有关蒙古国西部卫拉特系集团的农耕与自我认同的预备考察(日文)
微细铣削工艺数据库系统设计与开发
江苏省ETC数据库系统改造升级方案探讨
实时数据库系统数据安全采集方案
后台朋友
核反应堆材料数据库系统及其应用
日文花样