首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Tomcat服务器中奇怪的间歇字符编码行为

Tomcat服务器中奇怪的间歇字符编码行为
EN

Stack Overflow用户
提问于 2012-12-21 11:44:14
回答 1查看 445关注 0票数 1

在我们的生产环境中,我们不时地在Tomcat中遇到一个非常奇怪的编码问题。

我还不能准确地指出代码中的问题发生在哪里,但它涉及到将非ascii字符替换为近似ascii字符。

例如,用“a”替换字符“a”。由于该网站是瑞典语,所以“”、“”和“”是相当常见的。但出于某种原因,替换‘s’字符总是有效的,所以像“K inte grisen i s cken”这样的字符串就变成了"Kop inte grisen i s cken“,即‘a’没有按它应该的替换,而‘s’则是。

关于这个问题的一些快速事实:

  • 这种情况很少发生(我们注意到了3-4次,也许是在1-2年前)。
  • 重新启动故障服务器会使问题消失(直到下一次)。
  • 它从未同时发生在一个以上的前端服务器上。
  • 这种情况并不总是发生在同一个前端服务器上。
  • 不涉及前端的用户输入。
  • 所有前端服务器都连接到相同的CMS和DB,相关配置是相同的。
  • 所有前端服务器都具有相同的相关配置(linux、tomcat配置、java环境配置(如"file.encoding“等),并使用相同的脚本(都是根据主机/服务提供商)启动的。
  • 所有前端服务器对站点使用相同的war文件,使用相同的jar文件。
  • 在发生此字符替换问题时,在站点上看不到其他编码问题。
  • 我们从未能够在任何其他环境中再现这一问题。

由于CMS的需求,我们使用Tomcat5.5和Java 5。

我只能想到造成这种行为的两个看似合理的原因:

  1. 宿主提供商有时以不同的方式启动/重新启动前端服务器,可能是使用其他环境变量或其他文件访问权限的另一个用户帐户,也可能是使用一些不同于普通脚本的脚本。
  2. 在Tomcat或webapp启动期间运行的某些进程依赖于其他进程,有时(间歇但很少)这两个(或更多)进程以导致这种编码缺陷的顺序运行。

但是,即使上面的1或2是这样的情况,它仍然不能完全解释到底发生了什么。究竟有什么不同可以解释这一点呢?因为所有"file.encoding“、"file.encoding.pkg”、"sun.io.unicode.encoding“、"sun.jnu.encoding”和所有其他相关的环境变量都在所有前端机器上匹配(在问题发生时,使用调试页面进行可视化验证)。

有人能为这种奇怪的间歇性行为想出一些合理的解释吗?简单地升级Tomcat和/或Java版本并不是一个真正相关的答案,因为我们不知道这是否会解决问题,而且它仍然无法解释问题是什么。我更感兴趣的是,究竟是什么引起了这个问题。

看待/Jimi

更新:

我想我找到了执行字符替换的代码。在初始化时(由第一次调用替换触发),它构建一个HashMap,并按如下方式填充:

代码语言:javascript
复制
lookup.put(new Character('å'), "a");  

然后,当它应该替换字符串时,它会遍历每个字符,并对每个字符在哈希映射中以字符作为键进行查找,如果找到替换字符串,则使用原始字符。

这部分代码已经有3年多的历史了,并且是由一位早已离开的开发人员编写的。如果我今天重写这段代码,我会做一些完全不同的事情,这甚至可能解决问题。但它仍然无法解释到底发生了什么。有人能看到一些可能的解释吗?

EN

回答 1

Stack Overflow用户

发布于 2012-12-21 12:58:35

在进行替换之前,将输入规范化为普通形式C。

例如,ä可以是一个字符,U+00E4,也可以是两个字符,a (U+0061)和组合除氧U+0308

如果您的替换只查找组合的表单,那么分解后的表单仍将保持为\u0061\u0308,因为这两个表单都不匹配\u00e4

代码语言:javascript
复制
public static void main(String args[]) {
    String decomposed = "\u0061\u0308";
    String composed = "\u00e4";

    System.out.println(decomposed);
    System.out.println(composed);
    System.out.println(composed.equals(decomposed));
    System.out.println(Normalizer
            .normalize(decomposed, Normalizer.Form.NFC).equals(composed));

}

输出

代码语言:javascript
复制
ä
ä
false
true
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13989559

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档