特殊字符'\ u0098'使用charCodeAt()读作'\ u02dc'

时间:2012-04-09 22:19:07

标签: javascript servlets unicode character-encoding iso-8859-1

我正在使用Java创建test.js,如下所示。 Test.js实现函数d(),它接收参数特殊字符〜('\ u0098');

函数d()应显示此特殊字符的charCodeAt(),即152.但是,它显示732。

请注意字符152和732均由特殊字符〜表示,如下所示。

http://www.fileformat.info/info/unicode/char/098/index.htm

http://www.fileformat.info/info/unicode/char/2dc/index.htm

如何强制功能d()显示152而不是732? (charset问题?)。致谢

TEST.JAVA

public void doPost(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException
{
    res.setHeader("Content-Type", "text/javascript;charset=ISO-8859-1");
    res.setHeader("Content-Disposition","attachment;filename=test.js");
    res.setCharacterEncoding("ISO-8859-1");
    PrintWriter printer=res.getWriter();
    printer.write("function d(a){a=(a+\"\").split(\"\");alert(a[0].charCodeAt(0));};d(\""); // Writes beginning of d() function
    printer.write('\u0098'); // Writes special character as parameter of d()
    printer.write("\");"); // Writes end of d() function
    printer.close();
}

TEST.JS由TEST.JAVA

创建
function d(a)
{
  a=(a+"").split("");
  alert(a[0].charCodeAt(0));
};
d("˜"); // Note special character representing '\u0098'

的test.html

<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>
<body>
<script type="text/javascript" charset="ISO-8859-1" src="test.js"></script>
</body>
</html>

2 个答案:

答案 0 :(得分:5)

  

请注意,字符152和732均由特殊字符〜表示,如下所示。

不是真的。 ˜明确地表示字符U + 02DC(732),因此charCodeAt正在做正确的事情。字符U + 0098(152)是一个几乎从不使用的不可见控制代码。

诀窍是"ISO-8859-1"与Java和Web浏览器有不同的含义。对于Java,它确实是ISO-8859-1标准,它完全映射到Unicode的前256个代码点。这包括一系列很少使用的C1控制字符,分别为128-159。

然而,对于网络浏览器,"ISO-8859-1"实际上意味着Windows代码页1252(西欧),这是一种在128-159块中放入各种有用字符的编码。此行为源于刚使用计算机默认代码页的早期Web浏览器。当向浏览器添加适当的Unicode和编码支持时,兼容性问题决定了对Windows字符的持续支持,尽管它们标记为ISO-8859格式不正确。

因此,当您在ISO-8859-1中从Java编写U + 0098字符时,会得到一个0x98字节,然后由浏览器读取为U + 02DC。这通常是无害的,因为实际上没有人想要使用U + 0080-U + 009F范围内的C1控制代码。但它肯定令人困惑。

这个古老的怪癖,以及将128-159范围内的&#...;字符引用视为cp1252字节的相关内容,最终被记录并标准化为HTML5的一部分,但仅适用于HTML解析规则。 (不是XHTML5,因为它遵循更明智的XML规则。)这就是为什么引用的fileformat.info页面出现,误导地说,U + 0098呈现为˜

如果确实需要提取字符的cp1252字节数,则必须使用查找表来帮助您,因为JavaScript不会显示该信息。例如:

var CP1252EXTRAS= '\u20ac\u20ac\u201a\u0192\u201e\u2026\u2020\u2021\u02c6\u2030\u0160\u2039\u0152\u0152\u017d\u017d\u017d\u2018\u2019\u201c\u201d\u2022\u2013\u2014\u02dc\u2122\u0161\u203a\u0153\u0153\u017e\u0178';

function getCodePage1252Byte(s) {
    var ix= CP1252EXTRAS.indexOf(s);
    if (ix!==-1)
        return 128+ix;
    var c= s.charCodeAt(0);
    if (c<128 || c>=160 && c<256)
        return c;
    return -1;
}

你可能不想这样做。无论如何,通常答案不是使用ISO-8859-1,而是坚持使用旧的UTF-8(The Only Sensible Encoding™)。

在任何情况下,每个浏览器都不支持<script charset="...">,并且每个浏览器也不支持Content-Type: text/javascript;charset=...。没有一种可靠的方式在包含页面的不同编码下提供JavaScript。如果您不是100%,那么每个包含页面的内容将使用与您的脚本相同的编码,唯一安全的方法是保持JavaScript ASCII安全,输出JavaScript \unnnn序列而不是文字字节。

(与ASCII兼容的JSON编码器可以帮助您完成此操作。)

答案 1 :(得分:0)

尝试:

    printer.write('\\u0098');

JavaScript也理解\uNNNN,因此您可以使用所需的字符代码显式地形成字符串。