【问题标题】:How do I ensure that the text encoded in a form is utf8如何确保表单中编码的文本是 utf8
【发布时间】:2010-12-31 22:02:36
【问题描述】:

我有一个用户可以输入文本的 html 框。我想确保输入框中的所有文本都以 UTF-8 编码或在用户完成输入时转换为 UTF-8。此外,我不太明白在输入文本框时如何选择各种 UTF 编码。

通常我对以下内容感到好奇:

  • 当用户在文本框中输入内容时,浏览器如何确定要使用的编码?
  • javascript如何判断html文本框中字符串值的编码方式?
  • 我可以强制浏览器只使用 UTF-8 编码吗?
  • 如何将任意编码编码为 UTF-8(我假设有一个 JavaScript 库)?

** 编辑 **

删除了一些对我的目标不必要的问题。

本教程帮助我更好地理解了 JavaScript 字符代码,但有问题,并且在所有情况下都没有将字符代码真正转换为 utf-8。 http://www.webtoolkit.info/javascript-base64.html

【问题讨论】:

  • 问题太多了!我们是否必须全部回答才能发布答案?
  • @Mark Byers 一点也不,我觉得它们与我要解决的问题有关。前 4 个问题的答案让我更接近我的解决方案。

标签: javascript html encoding utf-8


【解决方案1】:
  • 当用户在文本框中输入内容时,浏览器如何确定要使用的编码?

它使用页面默认解码的编码。根据the spec,您应该能够使用<form> 元素的accept-charset 属性覆盖它,但是IE 有问题,所以您不应该依赖它(我已经看到几个不同的来源描述了几个不同的bugs,而且我面前没有所有相关版本的 IE 来测试,所以我会留在那里)。

  • javascript如何判断html文本框中字符串值的编码方式?

JavaScript 中的所有字符串都以 UTF-16 编码。浏览器会将所有内容映射到 JavaScript 的 UTF-16,并从 UTF-16 映射到页面编码的任何内容。

UTF-16 是从 UCS-2 发展而来的编码。最初,人们认为 65,536 个代码点对于所有 Unicode 来说就足够了,因此 16 位字符编码就足够了。事实证明并非如此,因此字符集扩展为 1,114,112 个代码点。为了保持向后兼容性,16 位字符集的一些未使用范围被留作代理对,其中两个 16 位代码单元用于编码单个字符。阅读UTF-16 and UCS-2 on Wikipedia了解详情。

结果是当你在 JavaScript 中有一个字符串 str 时,str.length 不会给你字符的数量,它会给你代码单元的数量,其中两个代码单元可以用来编码一个字符,如果该字符不在基本多语言平面内。例如,"abc".length 给你 3,但"???".length 给你 6;并且"???".substring(0,1) 给出了看起来像一个空字符串的内容,因为无法显示代理对的一半,但该字符串仍然包含该无效字符(我不保证这可以跨浏览器工作;我相信删除损坏的字符是可以接受的)。要获取有效字符,您必须使用"???".substring(0,2)

  • 我可以强制浏览器只使用 UTF-8 编码吗?

执行此操作的最佳方法是以 UTF-8 格式提供您的页面。确保您的 Web 服务器正在发送适当的 Content-type: text/html; charset=UTF-8 标头。您可能还希望在 <head> 元素中嵌入一个 <meta charset="UTF-8"> 元素,以防 Content-Type 未正确设置(例如,如果您的页面从本地磁盘加载)。

  • 如何将任意编码编码为 UTF-8(我假设有一个 JavaScript 库)?

在 JavaScript 中没有太多需要以特定编码对文本进行编码。如果您只是简单地写入 DOM,或者读取或填写表单控件,您应该只使用被视为 UTF-16 代码单元序列的 JavaScript 字符串。 XMLHTTPRequest,当通过 POST 用于 send(data) 时,将使用 UTF-8(如果您向它传递一个在 <?xml ...> 声明中声明的具有不同编码的文档,它可能会也可能不会将其转换为 UTF-8,所以为了兼容性,您通常不应该使用 UTF-8 以外的任何东西)。

【讨论】:

  • Web 浏览器认为 ISO-8859-1 是 cp1252 已被广泛接受,这不是 accept-charset 被破坏的原因。 IE 实际所做的是将accept-charset 视为仅当从页面本身获取的字符集无法保存表单字段的内容时使用的备份字符集。这意味着当您提交表单时,您无法知道 IE 是使用页面编码还是 accept-charset 编码对表单字段进行编码(实际上您很可能在表单中混合使用)。这使得无法恢复原始字符。
  • 好的,删除了对accept-charset的引用;经过一番研究,我看到几个来源对错误的描述不同,我面前没有所有相关版本的 IE 来测试,如果你将整个页面上的字符编码设置为 UTF,无论如何都没有必要-8.
  • 优秀的答案。此外,最终,接受 POST 的服务器最终将负责验证和过滤 POST 的内容。因为你不能保证提交 POST 的客户端确实运行了你的 javascript。
【解决方案2】:

文本框中的文本没有以任何方式编码;它是“文本”,一个抽象的字符系列。在几乎所有当代应用程序中,该文本都表示为一系列 Unicode 代码点,这些代码点是映射到特定抽象字符的整数。文本在变成字节序列之前不会被“编码”,就像提交表单时一样。那个时候,编码是由表单出现的HTML页面的编码决定的,或者由表单元素的accept-charset属性决定。

【讨论】:

  • 那么如果我想将该表单的值转换为字符串形式的十六进制等效值呢? ECMAScript 看到什么编码?
  • @e5 正如我在回答中所说,JavaScript 中的字符串显示为 UTF-16 代码单元的序列。如果您逐个字符地访问字符串,或检查它的长度,如果您有超出 BMP 的字符,您将看到代理代码点。
  • @Brian Campbell,感谢您的快速回复。什么是代理代码点? utf-16 字符的十六进制值和 javascript 给你的字符代码之间有什么关系?
  • e5:它们是一样的。 JavaScript(ECMAScript 标准)和 DOM(W3C DOM Level 1 Core)都将 UTF-16 代码单元指定为基本字符类型。代理代码单元是“代理对”的一部分,它在两个 UTF-16 代码单元中编码一个 Unicode 字符(代码点)。这种丑陋被证明是必要的,因为在几个版本的 Unicode 之后,很明显 65536 个字符是不够的。许多系统在其基本字符串类型中使用 UTF-16 代码单元,包括 Java 和 Windows。其他如 Linux 和 Python 可以支持不需要代理的更广泛的字符串类型。
【解决方案3】:

我想确保输入框中的所有文本都以 UTF-8 编码

HTML DOM 中的文本(包括输入字段)没有内在的字节编码;它存储为 Unicode 字符(具体来说,在 DOM 和 ECMAScript 标准级别,UTF-16 代码单元;在极少数情况下,您使用基本多语言平面之外的字符可能会看到差异,例如。'?'.length 是 2 )。

只有在发送表单时,文本才会使用特定编码序列化为字节,默认情况下与解析页面时使用的编码相同,因此您应该将包含表单的页面提供为 UTF-8(通过Content-Type 标头 charset 参数和/或等效的 <meta> 标记)。

虽然原则上在<form> 元素的accept-charset 属性中对此进行了覆盖,但它在IE 中无法正常工作(并且在许多情况下是有害的)。所以避免那个。

JavaScript 本身没有明确的编码处理函数。您可以通过链接 unescape(encodeURIComponent(str)) 来组合一个 Unicode 到 UTF-8 字节的编码器(反之亦然),但仅此而已。

【讨论】:

  • 我以前见过 unescape(encodeURIComponent(str)),但我担心它可能不适用于所有情况。
  • 它很可靠,几乎是唯一应该使用 escape/unescape 的东西(即使那样,你也很少需要它)。
  • unescape 已被弃用,取而代之的是 decodeURI。请参阅this SO question 了解更多信息。
  • @asciimo 您不能为此目的使用decodeURI,这与URI 无关。将 unescape 替换为 decodeURI[Component] 并不是一个好主意,除非您确定在使用 URI 解码时错误地使用了它,并且您确定没有没有escape 可能被更改破坏的数据。这些功能现在位于“网络浏览器遗留功能”附件中,但这并不意味着它们已被弃用或可能很快消失。用于此特定目的的新世界替代品是 Encoding API,但今天的支持太差了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-14
  • 2012-04-27
  • 1970-01-01
  • 2010-09-30
相关资源
最近更新 更多