- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我们都知道如何easy character sets are on the web ,但每次你认为你做对了,一个外国字符集就会咬你一口。所以我想追踪我将在下面描述的虚构场景中发生的事情的步骤。我会尽量写下我的理解,但我的问题是让你们纠正我犯的任何错误并填写任何空白。
在阅读这个场景时,想象一下这是 John 在 Mac 上完成的,而 Jane 在 Windows 上完成的,如果在任何特定情况下一个人的行为与另一个不同,请添加注释。
我们的英雄(约翰/简)首先用 Microsoft Word 写了一段话。 Word 的字符集是 BLANK1 ( CP1252 ?)。
他/她复制段落,包括巧妙的引号(例如“”)。复制行为由 BLANK2(操作系统...Windows/Mac?)完成,其中 BLANK3(检测应用程序使用的字符集并继承该字符集?)。然后他/她将该段落粘贴到 StackOverflow 的文本框中。
让我们假设 StackOverflow 在 Apache/PHP 上运行,并且它们在 httpd.conf 中的设置没有指定 AddDefaultCharset utf-8并且他们的 php.ini 设置了 default_charset符合 ISO-8859-1。
然而上面的字符集都无关紧要,因为 Stack Overflow 的标题包含这个语句 META http-equiv="Content-Type" content="text/html; charset=UTF-8" ,所以即使当您单击“提问”时,您可能已经在 firebug 中看到了 *RESPONSE 标题。 “内容类型文本/html;” ...事实上,Firefox/IE/Opera/Other browsers BLANK4(完全100%忽略服务器 header 并在 header 中使用Meta Content-type声明覆盖它?虽然它必须在知道Content-type之前读取文件,因为它在显示正文之前不必对编码做任何事情,所以这与浏览器没有什么不同?)。
由于页面的元内容类型是 UTF-8,因此输入表单会将您输入框中的任何字符转换为 UTF-8 字符。 BLANK5(如果有人可以详细了解浏览器在此步骤中的作用,那将非常有帮助......这是我的理解......因为操作系统控制剪贴板和表单中字符的显示,它插入复制它的任何字符集中的字符。并以该字符集的形式显示它......在此示例中覆盖 UTF-8)。
让我们假设表单 method=GET 而不是 post,这样我们就可以使用 URL 浏览器输入来播放.... 继续我们的故事,表单以 UTF-8 格式提交。代表十进制代码 147 和 148 的智能引号,当浏览器将它们转换为 UTF-8 时,它会被转换为 BLANK6 字符。
假设提交后,Stack Overflow 发现表单中存在错误,因此它不会显示结果问题,而是在表单中弹出带有您的问题的输入框。在 php 中,表单变量用 htmlspecialchars($var) 转义,以便正确显示数据,因为这次是 BLANK7(控制显示的浏览器,而不是操作系统......因此引号需要被表示为它的 UTF-8 等价物,否则你会得到可怕的有趣的问号?)
但是,如果您使用智能引号,并将它们直接插入到 URL 栏中并按回车键....htmlspecialchars 将执行 BLANK8,弄乱表单显示并插入问号�� 因为直接查询 URL 只会使用在 url 中编码...甚至是 BLANK9(编码混合?),如果你有不止一个...
当发出请求时,浏览器会向浏览器列出可接受的字符集。字符集列表来自 BLANK10。
现在你可能认为我们的故事到此结束,但事实并非如此。因为 StackOverflow 需要将这些数据保存到数据库中。幸运的是,经营这个联合的人很聪明。因此,当他们的 MySQL 客户端连接到数据库时,它会通过发出 SET NAMES UTF-8 来确保客户端和服务器以 UTF-8 进行通信。启动连接后立即执行命令。此外,MySQL 的默认字符集设置为 UTF-8,并且每个字段的设置方式相同。
因此,Stack Overflow 已经完全保护了他们的网站免受 dB 注入(inject)、CSRF 伪造和 XSS 站点脚本问题的影响……或者至少是那些由字符集游戏引起的问题。
*注意,这是一个示例,而不是该页面的实际响应。
最佳答案
我不知道这是否“回答”了您的“问题”,但我至少可以帮助您解决我认为可能是严重误解的问题。
您说,“由于页面的元内容类型是 UTF-8,因此输入表单会将您输入框中的任何字符转换为 UTF-8 字符。”没有“UTF-8 字符”这样的东西,在粘贴时将任何东西“转换”成任何东西的形式是不真实的,甚至没有意义。字符是一个完全抽象的概念,没有办法知道(不阅读源代码)给定的程序(包括您的 Web 浏览器)如何决定实现它们。由于当今最重要的应用程序都精通 Unicode,因此它们可能有一些内部抽象来将文本表示为 Unicode 字符——注意,这是 Unicode 而不是 UTF-8 .
Unicode(或任何其他字符集)中的一段文本表示为一系列 码点 , 唯一分配给 的整数字符 ,它们是大型数据库中的命名实体,每个实体都有任意数量的属性(例如它是否是组合标记,是否从右到左等)。这是橡胶与道路相遇的部分:为了代表真实计算机中的文本,通过将其保存到文件,或通过网络将其发送到其他计算机,它必须是 编码 作为一系列字节。 UTF-8 是 编码 (或 Unicode 说的“转换格式”),它将每个整数代码点表示为唯一的字节序列。特别是 UTF-8 有几个有趣和好的特性,但它们与理解一般情况下发生的事情无关。
在您描述的场景中,内容类型元数据告诉浏览器如何将发送的字节解释为字符序列(请记住,它们是完全抽象的实体,与字节或任何东西都没有关系)。它还告诉浏览器在返回服务器的途中将用户输入的文本值编码为 UTF-8 格式。
所有这些评论都适用于整个链条。当计算机程序处理“文本”时,它正在对一系列“字符”进行操作,这些字符是代表书面语言最小组成部分的抽象。但是当它想要将文本保存到文件中或将其传输到其他地方时,它必须将该文本转换为字节序列。
我们使用 Unicode 是因为它的字符集是通用的,并且因为它在其编码(UTF-8、UTF-16 和 UTF-32)中使用的字节序列是明确的。
附言当您看到 � 时,有两个可能的原因。
1) 一个程序被要求使用一些不包含出现在文本中的特定字符的字符集(例如 ISO-8859-1)编写一些字符。因此,如果文本在内部表示为 Unicode 代码点序列,并且要求文本编辑器保存为 ISO-8859-1,并且文本中包含一些日文字符,则它要么拒绝这样做,要么吐出一些任意的 ISO-8859-1 字节序列表示“没有 puedo”。
2) 程序接收到可能确实以某种编码表示文本的字节序列,但它使用不同的编码来解释这些字节。某些字节序列在该编码中是没有意义的,因此它可以拒绝这样做,或者只是选择某个字符(例如 �)来表示每个无法理解的字节序列。
P.P.S.这些编码/解码舞蹈发生在您选择的操作系统中的应用程序和剪贴板之间。想象一下可能性。
回复您的评论:
“Word 使用 CP1252 编码”是不正确的;它在内部使用 Unicode 来表示文本。您可以通过将一些片假名字符(例如 サ)粘贴到 Word 中来简单地验证这一点。 Windows-1252 不能表示这样的字符。
当您从任何应用程序“复制”某些内容时,完全由应用程序决定在剪贴板上放置什么内容。例如,当我在 Word 中执行复制操作时,我看到 17 条不同的数据被放入剪贴板,每条数据具有不同的格式。其中之一的类型为 CF_UNICODETEXT,恰好是 UTF-16。
现在,至于网址...详情可见here .在发送 HTTP 请求之前,浏览器必须将 URL(可以包含任何文本)转换为 IRI。您首先将 URL 编码为 UTF-8,然后通过百分比转义形式表示 ASCII 可打印范围之外的 UTF-8 字节,从而将 URL 转换为 IRI。因此,例如,http://foo.com/dir1/引き割り.html 的正确编码是 http://foo.com/dir1/%E5%BC%95%E3%81%8D%E5%89%B2%E3%82%8A.html . (主机名遵循不同的规则,但都在链接到的资源中)。
现在,在我看来,浏览器应该在地址栏中显示纯旧文本,并在幕后进行所有编码。但是有些浏览器做出了愚蠢的选择,它们会向您显示 IRI 表单,或者 URL 和 IRI 的一些组合。
关于http - 请帮助我跟踪如何在每一步处理字符集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1542107/
我是一名优秀的程序员,十分优秀!