保存非英文字符时出现问题

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=utf8Collat​​ion=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ગુજ。请注意,大多数古吉拉特语十六进制应采用E0AAyyE0AByy 的形式。您还可以找到 20 的空格。

我很抱歉没有更确定。十年来我一直在处理字符集问题,但这是一个新变体。

【讨论】:

P.S.我没能更快地解决它,因为我看到了àªà«àª,这与你的àª?à«?àª? 不太一致。我仍然无法解释那部分。但这应该没关系;十六进制更明确。 试过你的解决方案,它对我不起作用。好像我在配置方面错过了一些东西。 在您的“MySQL url”中,您只有 outbound 设置 (&amp;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 设置为休眠属性&lt;prop key="hibernate.connection.characterEncoding"&gt;UTF-8&lt;/prop&gt;,确保将其明确添加为数据库 url 上的连接变量,所以

jdbc:mysql://host:port/dbName?useUnicode=true&amp;characterEncoding=UTF-8&amp;connectionCollation=utf8_general_ci&amp;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 数据库时出现异常

ORA-06502: PL/SQL: 尝试将 XML 保存到文件时出现数字或值错误

路径超过 260 个字符时出现 System.IO.DirectoryNotFoundException [重复]