整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

HTML代码中的空格和空行

子1:(文本内容中的连续空格)

<p>这段文本中,输入连续的空格          大概输入了十个。</p>

显示效果:“格”和“大” 之间的是个空格显示出来只是一个空格。

这段文本中,输入连续的空格 大概输入了十个。

例子2:(代码之间的连续空格)

<span>span是一个行内标签</span>               <span>和前面的span元素之间隔了很多个空格</span>

显示效果:两个span元素之间连续的空格,显示出来即"签"与“和”之间的空格,只有一个空格。

span是一个行内标签 和前面的span元素之间隔了很多个空格

上面两个例子证明:HTML代码中连续的空格在显示时会显示为一个空格,其余的多余的空格会被移除或者说被忽略。

段落文本其实也是HTML代码的一部分,只不过它在p标签内部,而例子2的空格是在两个span标签之间。


理解了空格,现在看看空行,同理

例子3:(文本内容中的空行)

<p>这段文本中,输入连续的空行





大概输入了五行。</p>

显示效果:如我们所见,文本代码中的五行空行,显示出来也只是一个空格。

这段文本中,输入连续的空行 大概输入了五行。

例子4:(元素之间/标签之间的空行),只要把例子2中的空格换成空行就可以了,显示效果和例子2的一样,多行空行都只会显示为一个空格。

<span>span是一个行内标签</span>





<span>和前面的span元素之间隔了很多空行</span>


span是一个行内标签 和前面的span元素之间隔了很多空行

得证:HTML 代码中的所有连续的空格或空行(换行)都会被显示为一个空格。


既然如此,如果我们希望扩大两个字符之间的间距,让代码中的连续空格或空行显示出来的结果也是连续的空格或空行,那该怎么办?其实很简单。

方法一:我们可以用预格式化标签<pre>,无论是空格或空行都适用。

<pre>
这是
预格式文本。
它保留了      空格
和换行。
</pre>

显示效果

这是
预格式文本。
它保留了      空格
和换行。


方法二:我们可以用空格实体符 代替空格,用换行标签<br/>代替空行。虽然这种方法可以得到我们想要的显示效果,但是对搜索引擎不是最友好的方式,因为 和<br/>在HTML中都是没有语义的。所以建议尽量少用。另外需要注意的是, 必须小写,而且最后面的分号是不能省略的。


方法三:(适合空格)使用全角空格

全角空格被解释为汉字,所以不会被被解释为HTML分隔符,可以按照实际的空格数显示。

问题:怎么使用全角输入法?

以搜狗输入法为例,我们通常使用的是半角输入,其状态栏中有个月亮的标志,就说明正在使用的是半角输入,如果是太阳的标志,就说明使用的是全角输入。全角/半角的切换可以通过点击标志,也可以通过快捷键 Shift+Space(空格符)切换。

半角输入(月亮)

全角输入(太阳)

方法四:使用CSS样式中字间隔属性控制,CSS中的word-spacing 属性可以改变字(单词)之间的标准间隔。我们知道英文中两个单词之间是通过空格隔开的,所以我们视觉上可以这样认为,word-spacing改变了(拉长或缩短)单词之间那个空格的宽度。

方法五:使用CSS样式中的white-space 属性,这个属性声明如何处理元素内的空白符。

描述

normal

默认。空白会被浏览器忽略。

pre

空白会被浏览器保留。其行为方式类似 HTML 中的 <pre> 标签。

nowrap

文本不会换行,文本会在在同一行上继续,直到遇到 <br> 标签为止。

pre-wrap

保留空白符序列,但是正常地进行换行。

pre-line

合并空白符序列,但是保留换行符。


white-space:normal;就是正常,和不设置一样,连续空格和空行都只会显示一个空格。

white-space:nowrap;不换行是什么意思呢?正常情况下,当我们的文本超出了文本域,文本就会自动折行,这个设置就是说不自动折行了,而是碰到换行标签<br />才换

white-space:pre;和方法一相同,将文本原样输出显示。当文本超出文本域时,不换行,会产生滚动条。

white-space:pre-wrap;保留空格和空行,但当文本超出文本域时,会自动换行。

white-space:pre-line;连续的空格会显示为一个空格,但保留连续的空行。

是why技术的第20篇原创文章

本周本来是没有时间写技术文章的,为了周更不断,想着去把之前发布在其他平台的一篇原创文章搬过来就行。结果发现,当年我写的那篇文章,离真相还差着十万八千里。

而去搜索这个问题时,我的文章是检索结果的第一个

原文《http请求参数中加号被替换为空格及请求参数被URLDeCode的记录》链接如下:

https://www.jianshu.com/p/1a30b585c39e

所以为了避免继续误导读者,就算周末"爆肝",也得输出此文,不得不发。

这是我作为程序员的自我修养。

加号变空格

之前写那篇文章的原因是碰到了两个有趣的问题,如下

首先,我们进行场景复现,搭建项目的过程就不说了,用idea+springboot搭建一个简单的web项目还不是信手拈来的事?

正如上面的现象所示:我的入参是jay+love,但是后台接收到的是jay love,加号变空格了。为什么呢?

源码之下无秘密

本文分析的Tomcat源码版本为:9.0.29.

通过Debug可以找到两处关键的代码:

第一处:

org.apache.tomcat.util.http.Parameters#processParameters(byte[], int, int, java.nio.charset.Charset) 下图中的290行

在这个地方因为有'+',所以把decodeValue参数设置为true,表示需要对请求中的value进行decode操作。

decode的具体的源码位置如下,也就是第二处关键代码:

org.apache.tomcat.util.buf.UDecoder#convert(org.apache.tomcat.util.buf.ByteChunk, boolean)


可以看到,在源码里面有一段代码,是把'+'替换了为了空格,是特意做了这样的特殊处理。

整个方法的解读如下:

所以我的入参是jay+love,但是后台接收到的是jay love,加号变空格了。为什么呢?

原因很简单,在源码中有一段代码把'+'替换成了空格,刻意为之。

为什么这样做呢?

之前的文章里面我写的是:

由于历史原因,那到底是什么历史原因呢?

我在网上查了一圈,没有找到具体的历史原因,我看到的所有的关于这个问题的文章,要么只是给了解决方案,要么就是上面这一句历史原因,一带而过,含糊其辞。

这里,我就明明白白的告诉你为啥。

经过我长时间的摸排,我找到了很多蛛丝马迹,整理之后,我决定从JDK的一个"BUG"讲起。

对应链接:http://bugs.sun.com/view_bug.do?bug_id=4616184

从提交时间上可以看出,该问题早在2001年,距今18年前就有人指出来了,并给JDK上报了BUG,他的描述如下:

首先,我们先把他的测试代码拿出来跑一下:

他为什么说空格encode之后应该是%20呢?

因为他在BUG里面提到了RFC2396标准。(RFC就不解释了,你只要知道是业界认证的权威标准就行):

http://www.ietf.org/rfc/rfc2396.txt

在RFC2396的第2.4.1节,明确的说了:"%20"是US-ASCII空格字符的转义编码。

去查询标准的ASCII码你也可以发现确实是这样的:

用代码实践一下,证明以上结论:

看java.net.URLEncoder#encode(java.lang.String, java.lang.String)的源码也可以直观的看到,源码里面做了特殊处理

再看java.net.URLDecoder#decode(java.lang.String, java.lang.String)的源码:

这里就和前面的呼应上了,这处理方式,一模一样呀。所以为什么这样处理,两处地方属于同宗同源啊!

而提BUG的那个哥们为什么觉得这是一个BUG呢?

虽然经过试验,'+'和'%20'经过decode都能转化为空格,但是他认为,根据RFC2396来讲,这里只能是'%20',怎么能变成'+'呢?所以他觉得这是一个BUG。

那我们看看JDK官方是怎么回复这个问题的呢?

官方回复:

这不是BUG啊,朋友!这个类就是遵循了HTML规范中的规定:如何对 HTML表单中的URLs进行encode。它不打算用于其他用途。


而这样做的原因,是因为包括HTML 4.01第17.13.4节和RFC 1866(已经被W3C HTML推荐标准取代)都是这样规定的。

对于第一段话,官方的意思我理解是:这个类就是拿来对url进行encode的,不做其他用途。因为你调用了encode编码,那就需要decode解码,我只要保证你解码之后的数据和你encode之前的数据是一样的就行了。你要拿去搞其他事情,我就管不了了。

而为什么这样做呢?是因为规定就是这样的呀,类似于国家标准就是这样的,类似于产品经理提出的需求就是这样的呀。这里官方提出了两个标准,一个是HTML 4.01,一个是RFC1866(这个已经被其他的标准取代了,那我们就只看HTML 4.01)。

HTML4.01是1999年12月24日发布的,在HTML4.0基础上进行微小改进,W3C推荐标准 。


在w3c上找到该标准,地址如下

https://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1

下图圈起来的地方很关键,可以点开放大查看:

找到HTML 4.01第17.13.4节,其中明确指出:当content-type为application/x-www-form-urlencoded时,对names和vaules进行转义,空格用'+'代替。

HTML 4.01第17.13.4节原文如下:

Control names and values are escaped. Space characters are replaced by `+'

官方举的虽然是HTML 4.01的例子,但是我翻译了历史文献,发现其实在更早的HTML 3.2规范中就规定了,HTML 3.2规范在1996年就成为了W3C推荐标准,其中相关内容如下:

链接地址:https://www.w3.org/TR/2018/SPSD-html32-20180315/

而application/x-www-form-urlencoded是浏览器默认的content-type。

在BUG里面提到的RFC2396标准是1998年8月提出来的

HTML 3.2规范在1996年就成为了W3C推荐标准

所以,我觉得这就是历史原因!

再说一次,在HTML 4.01规范中就明确规定了:当content-type为application/x-www-form-urlencoded时,对names和vaules进行转义,空格用'+'代替。

没有原因,就是规定!我在查询的过程中发现,其他的编程语言也有这样的问题,因为他们都遵从同样的标准,就有了同样的"历史原因"。

回到前面的这个地方:

这里解码的时候为什么把'+'转化为空格呢?因为"历史原因",如果URLs中出现了空格,需要用'+'替换,所以这里解码的时候把'+'转化回了空格。先有了编码的操作,所以才会有解码的操作。

很多的文章都在说这是'+'的原因,甚至有的文章说'+'的编码应该改为%20。但是其实上面分析过了,有问题的是空格,而不是'+'。

那为什么我们在做表单提交的时候,也经常写'+'号呀,为什么没有问题呢?

因为当Html的表单被提交时, 每个表单域都会被Url编码之后才在被发送,下面的小例子可以佐证:

解决方案

解决方案网上一大堆了,我这里罗列一下吧:

方案一:修改客户端,将客户端带'+'的参数中的'+'全部替换为‍'%2B',如下:

方案二:修改服务器端,将空格替换为'+',这种方式只适用于参数中'+'没有空格的情况。如下:

方案三:修改服务器端,将获取参数的方法由‍reuqest.‍getParameter改为‍request.getQueryString(),然后对得到的字符串进行解析。

最后说一句

正如我文章最开始说的,就算是熬夜爆肝,我也必须得输出这篇文章,因为我最开始的文章不仅写的表面,而且还有一些问题,我得对其进行纠正。

让我突然想起了之前和朋友的一次对话,他问我说:你作为程序员,时刻待命,只要系统一出问题你就立马会响应。你不觉得累吗?

我回答道:说真的,当系统出问题,需要我排查问题的时候,我不觉得累。因为这个系统是我负责的,代码是我自己一行行的写出来的。出现了问题,我得证明我的系统是没有问题的,是不是别人的打开方式不对。但是如果真的是我的代码导致的问题,我会心有愧疚,我也得立即响应,对其负责。

这是我作为一个程序员的自我修养。

这篇文章的风格和《这道面试题我真不知道面试官想要的回答是什么》有点相似,全文描述的都是很小的知识点,甚至可以说是冷知识。一句话就能说出表面上的为什么,提炼出一个知识点。

但是我觉得提炼出来的,是一个干瘪瘪的知识点,它不够丰富,没有探索的过程。

而我所展示的是我去寻找这个问题的答案的过程。通过JDK的"BUG"把几个协议串联起来,而且是全世界共同遵循的协议,极具权威性。

才疏学浅,难免会有纰漏,如果你发现了错误的地方,还请你留言给我指出来,我对其加以修改。

感谢您的阅读。

以上。

击右上方红色按钮关注“小郑搞码事”,每天都能学到知识,搞懂一个问题!

由于HTML代码的空格通常会被浏览器忽略,所以我们很有必要对浏览器处理空格的一些规则有个详细的认识,这样我们后面才能详述它的解决办法。

一、默认规则

效果是这样的:

由此可此可以知道浏览器的默认处理规则一:文字的前后空格都会忽略,内部连续空格只有自作一个。

原样输出可能是我们这样写代码的本意,要让这段代码原样输出的方法有两个(使用标签/使用表示空格的实体代码):

方法一:<pre><span class="space"> 小郑 搞码 </span></pre>

方法二:<span class="space"> 小郑 搞码 </span>

二、另一个规则

关于规则部分还有一点,来看一段代码:

效果是:

表示,浏览器对字符的处理不仅限于空格,还有制表符(\t),换行符(\r和\n)。

同样让这段代码换行可能是我们写的本意,让这段代码换行的方法有两个:

方法一:套一个pre标签

方法二:<span class="space">小郑<br/>搞码</span>

最后总结一下:

HTML语言的空格处理,基本上就是直接过滤。这样的处理过于粗糙,完全忽视了原始文本内部的空格可能是有意义的。所以CSS提供了一个属性white-space属性来灵活控制空格。下篇详述。