保存非英文字符时出现问题
Posted
技术标签:
【中文标题】保存非英文字符时出现问题【英文标题】:Issue while saving Non-English character 【发布时间】:2015-10-27 03:58:17 【问题描述】:我们正在使用一个应用程序,我们需要以 Gujarati
语言保存数据。
Applcation 中使用的技术如下。
Spring MVC 版本 4.1.6.RELEASE 休眠版本 4.3.5.Final mysql 6.0.11我的 JSP 配置为
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
和
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
休眠配置是
<prop key="hibernate.connection.useUnicode">true</prop>
<prop key="hibernate.connection.characterEncoding">UTF-8</prop>
<prop key="hibernate.connection.charSet">UTF-8</prop>
MySQL 网址是
jdbc:mysql://host:port/dbName?useUnicode=true&connectionCollation=utf8_general_ci&characterSetResults=utf8
Pojo 有 String
字段来存储该数据。
MySQL 有 VARCHAR
数据类型来存储具有 charset=utf8 和 Collation=utf8_general_ci 的数据
当我尝试保存任何非英语(古吉拉特语)字符时,它会显示一些垃圾字符,例如 àª?à«?àª?
用于“ગુજ”。
这里有没有我遗漏的其他配置。
【问题讨论】:
看起来您正试图通过 JSP 页面进行保存。在处理请求之前,您是否执行过 request.setCharacterEncoding("UTF-8") 或类似操作?你可以通过单元测试来试验保存吗? 是的,出于测试目的,我创建了带有 url 模式 /* 的过滤器并在其中写入 request.setCharacterEncoding("UTF-8") 。在这种情况下,它将所有字符转换为? (问号)。 请提供SELECT col, HEX(col) FROM tbl WHERE ...
。这将帮助我诊断它是否正确插入但读取不正确,反之亦然。
如果您看到的问号与您的字符一样多,那可能没问题,但您可以更确定在更改调试器字体后检查字符。或者,您可以检查通过 string.getBytes() 获得的字节值。
@Rick: HEX(col) 结果 C3A0C2AAC297C3A0C2ABC281C3A0C2AAC29C 为ગુજ。
【参考方案1】:
我在将“泰米尔语”字符插入数据库时遇到了同样的问题。经过大量冲浪后,我得到了一个更好且有效的解决方案,它解决了我的问题。在这里我与以下人员分享我的解决方案你。我希望它能帮助你消除对那个非英语角色的疑虑。
INSERT INTO
STUDENT(name,address)
VALUES
(N'பெயர்', N'முகவரி');
我正在使用示例,因为您没有向我提供您的表和字段名称的任何结构。
【讨论】:
这并不能真正回答问题。【参考方案2】:我假设您想要ગુજ
(带有元音符号 U 的 GA JA)?
我认为您以某种方式指定了“latin5”。 (是的,我看到你到处都有 UTF-8,但是“latin5”是我可以让事情正常工作的唯一方法。)
CONVERT(CONVERT(UNHEX('C3A0C2AAC297C3A0C2ABC281C3A0C2AAC29C')
USING utf8) USING latin5) = 'ગુજ'
另外,你最终得到了“双重编码”;我怀疑是这样的:
客户端的字符编码为 utf8(良好);和 使用了SET NAMES latin5
,但它谎称客户端有latin5编码;和
表中的列声明为CHARACTER SET utf8
(良好)。
如果可能,最好重新开始 -- 清空表,确保有SET NAMES utf8
或在从客户端连接到数据库时建立 utf8。然后重新填充表格。
如果您想尝试恢复现有数据,这可能工作:
UPDATE ... SET col = CONVERT(BINARY(CONVERT(
CONVERT(UNHEX(col) USING utf8)
USING latin5)) USING utf8);
但是您需要为每个表中的每个混乱列都这样做。
对该代码进行部分测试
SELECT CONVERT(BINARY(CONVERT(
CONVERT(UNHEX(col) USING utf8)
USING latin5)) USING utf8)
FROM table;
我说“部分测试”是因为looking
正确可能无法证明is
正确。
在UPDATE
之后,SELECT HEX(col)
得到E0AA97E0AB81E0AA9C
为ગુજ
。请注意,大多数古吉拉特语十六进制应采用E0AAyy
或E0AByy
的形式。您还可以找到 20
的空格。
我很抱歉没有更确定。十年来我一直在处理字符集问题,但这是一个新变体。
【讨论】:
P.S.我没能更快地解决它,因为我看到了àªà«àª
,这与你的àª?à«?àª?
不太一致。我仍然无法解释那部分。但这应该没关系;十六进制更明确。
试过你的解决方案,它对我不起作用。好像我在配置方面错过了一些东西。
在您的“MySQL url”中,您只有 outbound 设置 (&characterSetResults=utf8
)。我不知道应该在那里,但也许是characterEncoding=UTF-8
【参考方案3】:
您可能会错过一些事情。我在 linux 上使用 mysql 时遇到了同样的问题,我要做的就是像这样编辑my.cnf
:
[client]
default-character-set = utf8
[mysqld]
character-set-server = utf8
例如在 Centos 上,此文件位于 Windows(我的电脑)C:\ProgramData\MySQL\MySQL Server 5.5\my.ini
上的 /etc/my.cnf
。请注意,ProgramData
可能会被隐藏。
另外,如果您使用 Tomcat,您必须为 URI 编码指定 UTF-8。只需编辑 server.xml
并修改您的主要 Connector
元素:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
URIEncoding="UTF-8"
redirectPort="8443" />
还要确保您在应用程序中添加了字符编码过滤器:
@WebFilter(filterName = "CharacterEncodingFilter", urlPatterns = "/*")
public class CharacterEncodingFilter implements Filter
@Override
public void init(FilterConfig filterConfig)
throws ServletException
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException
HttpServletRequest request = (HttpServletRequest) servletRequest;
request.setCharacterEncoding("UTF-8");
servletResponse.setContentType("text/html; charset=UTF-8");
filterChain.doFilter(request, servletResponse);
@Override
public void destroy()
希望这会有所帮助。
【讨论】:
【参考方案4】:另一个提示,不要只将characterEncoding
设置为休眠属性<prop key="hibernate.connection.characterEncoding">UTF-8</prop>
,确保将其明确添加为数据库 url 上的连接变量,所以
jdbc:mysql://host:port/dbName?useUnicode=true&characterEncoding=UTF-8&connectionCollation=utf8_general_ci&characterSetResults=utf8
此外,由于有很多层会丢失编码,您可以尝试隔离层并更新问题。例如。如果它在存储到数据库时,或者在之前的某个时间
【讨论】:
【参考方案5】:你的 applicationContext 文件应该是这样的:
为了让Spring MVC应用支持国际化,注册两个bean:
SessionLocaleResolver 注册一个“SessionLocaleResolver”bean,将其命名为完全相同的字符“localeResolver”。它通过从用户会话中获取预定义属性来解析语言环境。 笔记 如果您没有注册任何“localeResolver”,则将使用默认的 AcceptHeaderLocaleResolver,它通过检查 HTTP 请求中的接受语言标头来解析语言环境。
LocaleChangeInterceptor 注册一个“LocaleChangeInterceptor”拦截器并将其引用到任何需要支持多种语言的处理程序映射。 “paramName”是用于设置语言环境的参数值。
<bean id="localeResolver"
class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
<property name="defaultLocale" value="en" />
</bean>
<bean id="localeChangeInterceptor"
class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="language" />
</bean>
<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping" >
<property name="interceptors">
<list>
<ref bean="localeChangeInterceptor" />
</list>
</property>
</bean>
<!-- Register the bean -->
<bean class="com.common.controller.WelcomeController" />
<!-- Register the welcome.properties -->
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="welcome" />
</bean>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
native2ascii 是 JDK 中内置的一个方便的工具,用于将具有“非拉丁 1”或“非 Unicode”字符的文件转换为“Unicode 编码”字符。
Native2ascii 示例
-
创建文件 (source.txt)
创建一个名为“source.txt”的文件,里面放一些汉字,保存为“UTF-8”格式。
-
native2ascii
使用 native2ascii 命令将其转换为 Unicode 格式。
C:>native2ascii -encoding utf8 c:\source.txt c:\output.txt
native2ascii 会读取“c:\source.txt”中的所有字符,并将其编码为“utf8”格式,并将所有编码后的字符输出到“c:\output.txt”
-
读取输出
打开“c:\output.txt”,你会看到所有编码的字符,例如\ufeff\u6768\u6728\u91d1
welcome.properties
welcome.springmvc = \u5feb\u4e50\u5b66\u4e60
调用上面的字符串并将值存入数据库。
如果你想在 JSP 页面中显示它:
记得加一行
“”
在 jsp 页面顶部,否则页面可能无法显示 UTF-8 (中文)字符正确。
【讨论】:
以上是关于保存非英文字符时出现问题的主要内容,如果未能解决你的问题,请参考以下文章
python - 使用 Django 将 Unicode 字符存储到 MySQL 时出现问题
关于encodeURIComponent编码非UTF-8字符时出现的怪异情况
尝试将用户电子邮件和姓名保存到 Firebase 数据库时出现异常