2

我正在从 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?(字符集问题?)。谢谢

测试.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'

测试.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>
4

2 回答 2

4

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

并不真地。˜是明确的字符 U+02DC (732),charCodeAt做正确的事也是如此。字符 U+0098 (152) 是一个几乎从不使用的隐形控制代码。

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

然而,对于 Web 浏览器,"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 编码器可以帮助您做到这一点。)

于 2012-04-09T23:59:09.660 回答
0

尝试:

    printer.write('\\u0098');

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

于 2012-04-09T22:22:51.087 回答