谈谈不换行空格

简介:

昨天工作中遇到了一个问题问题:php程序从数据库中取出变量a"carws"iconvutf8gb2312a(值为"carws"),经过iconv转码从utf8到gb2312后,赋值给b,结果判断语句a==a==b 竟然是false!

究其原因原来是这里的空格是不换行空格。

什么是不换行空格?

不换行空格(non-blocking space)也是一种空格,它和普通空格的区别在于在排版的时候表现不同。比如在word中,下面一段话在“如果它”三个字中间有两个空格,第一段是使用普通空格的排版表现,第二段是使用不换行空格(word中输入不换行空格使用ctrl+shift+space)的排版表现。

Image(2)

第一段中“如”和“果”字中间的空格就被换行了,而第二段中的“如果它”三个字中的不换行空格就像是告诉word:这三个字是连在一起的,你如果要进行换行,就把我们一起进行换行,不能从中间隔断~所以谓之“不换行空格”。

在html中也有不换行空格的概念,&nbsp(本身就是non-blocking space的缩写)。在html中使用&nbsp也能达到不换行的目的,比如下面这个例子:

Image(3)

文字中的“排版时”三个字中间有空格,第一段使用普通空格,第二段使用&nbsp(html字符集中的non-blocking),第三段使用UTF-8字符集中的non-blocking space(我是直接从word中复制出来的,sublime text中如何输入non-blocking space没查出来,有知道的麻烦告诉一下)

在浏览器下显示情况:

Image(4)

之所以这么表现的原因和word中是一样的。

在HTML中,页面会合并多个连续的空格,而不换行空格是禁止合并的,因此它也称为“硬空格”,“固定空格”。

不同编码中的不换行空格

在不同编码下的不换行空格有不同的值设定,比如

在UTF8中,值为0xC2,0xA0(所以使用urlencode编码不换行空格会显示%c2%a0)

在HTML中,值为&nbsp,或者&#160(可以参考HTML特殊字符对照表http://www.jb51.net/onlineread/htmlchar.htm)

下图是不换行空格在不同字符集的表示

Image(5)

编码转换中的损失

从上张表中可以看出,最大的问题就是不换行空格并不是在所有编码中都存在,比如在我们经常使用到的GBK,GB2312,GB18032中都是没有不换行空格的。于是在字符转码中就会遇到问题了,主要归结于从一个有不换行空格的编码转换到没有不换行空格的编码的时候,程序会怎么处理这个不换行空格?

在php中,看下面这个程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
$normalspace  = " " ;
$nonblockingspace  = " " ;
echo  urlencode( $normalspace ), PHP_EOL;
echo  urlencode( $nonblockingspace ), PHP_EOL;
 
$normalspace_gb2312  = iconv( "UTF-8" , "GB2312" , $normalspace );
$nonblockingspace_gb2312  = iconv( "UTF-8" , "GB2312" , $nonblockingspace );
 
echo  urlencode( $normalspace_gb2312 ), PHP_EOL;
echo  urlencode( $nonblockingspace_gb2312 ), PHP_EOL;
 
$normalspace_gb2312_2  = iconv( "UTF-8" , "GB2312//TRANSLIT" , $normalspace );
$nonblockingspace_gb2312_2  = iconv( "UTF-8" , "GB2312//TRANSLIT" , $nonblockingspace );
 
echo  urlencode( $normalspace_gb2312_2 ), PHP_EOL;
echo  urlencode( $nonblockingspace_gb2312_2 ), PHP_EOL;

(其中的nonblockingspace是不换行空格,在vim中是使用ctrl +k, shift +N, shift +S打出来的)

输出:

Image(6)

在iconv的out_charset不加//IGNORE或者//TRANSLIT的情况下出现的Notice就是提示说这里的nonblockingspaceGB2312iconvnonblockingspace在GB2312中是没有的,强制转换可能会出现问题。然后在iconv中就把它过滤掉(准确来说是从开头到第一个非法字符截断了),因此nonblockingspace_gb2312 是空字符串。

而iconv加上了//TRANSLIT之后,php程序会去GB2312字符集中寻找和不换行空格最相近的一个字符(也就是空格),因此$nonblockingspace_gb2312_2是普通空格。

解决问题

到这里最初的问题就完全可以理解了

php程序从数据库中取出变量a"carws"iconvutf8gb2312a(值为"carws"),经过iconv转码从utf8到gb2312后,赋值给b,结果判断语句a==a==b 竟然是false!

 

首先我的数据库一定是支持不换行空格的字符集(我的数据库是UTF-8编码的)在库中存的变量acar[]wsa实际上是car[不换行空格]ws。程序取出变量a后中间就带有了不换行空格,再经过iconv转换后,不管是使用//IGNORE,//TRANSLIT,还是不做任何处理,它们两个都不可能是相等的了。

于是就知道了解决办法,在转码之前先做一次replace操作,否则转码后就是不可逆的了。

a=strreplace("","",a=strreplace("","",a);

 

于是我和我的小朋友们不用再郁闷了。

目录
相关文章
如何去掉字符串开头,结尾或者中间的空格及其他不想要的字符
去掉文本字符串开头,结尾或者中间不想要的字符,比如空白。
|
6月前
|
小程序
小程序换行
小程序换行
121 0
|
11月前
|
Unix C语言 C++
正确理解回车与换行
回车 \r 本义是光标重新回到本行开头 换行 \n 本义是光标往下一行(不一定到下一行行首)
115 0
|
算法 安全
每日算法刷题Day7-比较字符串大小,去掉多余的空格,单词替换
⭐每日算法题解系列文章旨在精选重点与易错的算法题,总结常见的算法思路与可能出现的错误,与笔者另一系列文章有所区别,并不是以知识点的形式提升算法能力,而是以实战习题的形式理解算法,使用算法。
212 0
每日算法刷题Day7-比较字符串大小,去掉多余的空格,单词替换
VB编程:去除文本框首尾空行-51
VB编程:去除文本框首尾空行-51
159 0
换行后怎么有一个空格?
换行后怎么有一个空格?
299 0
|
算法 Java C++
字符串,把这个碍眼的空格给我换掉!
字符串,把这个碍眼的空格给我换掉!
字符串,把这个碍眼的空格给我换掉!
|
Android开发
安卓资源字串中加全角空格、半角空格、换行、@%等特殊字符
安卓资源字串中加全角空格、半角空格、换行、@%等特殊字符
241 0