看不见的空格

空格看得见吗?空格本来就看不见… 但是一般的空格起码可以选中!

最近一个礼拜内竟然被这个零宽度空格坑了两次!

 

什么是零宽度空格?

它是一个Unicode字符,它是一个空格,它没有宽度!

什么叫没有宽度?就是如果2个字母之间打了一个零宽度空格,你是看不见任何东西的…两个字母还是会挨在一起。

而且坑爹的是,就算你用的是等宽字体,它也看不见…

 

会有什么问题

我自己竟然会在短短的一周内被这个坑了两次:

 

源代码中包含零宽度空格

那天我正在写一个 java bean,需要用作序列化和反序列化。

在写单测的时候,自己手动写了一串json,然后传入后反序列化。

结果一直报错!java 中反序列化的时候如果字段名不一致就会报错,可是我的字段名没有写错啊!

然后我试着先序列化,然后把序列化出来的string反序列化,结果它成功了…

 

我快崩溃了!两串string完全看不出任何区别!

到最后是怎么发现的呢?我保存到了文本文件后不小心用 VIM 打开了它,忽然发现了玄机所在!

vim

 

数据中的零宽度空格

另外一个坑是在业务中遇到的。用户在录入数据的时候输入了一个号码:ABC1234567

从页面上看一切正常,但是在 SqlServer Management Studio 中看中间却有一个问号,ABC123?4567

又崩溃了!如果你之前不知道令宽度空格的话,你能想到这是什么原因吗?编码问题?程序问题?数据库问题?

页面上看起来一切都是好的啊…

 

怎么避免

吃一堑长一智,以后再有这样诡异的问题,我一定第一时间复制粘贴到 VIM 中查看。

高级编辑器中都是看不见这个符号的,只有 VIM 这种古老的编辑器才能看到。对了,git 的 diff 也可以看到!

另外,我也不知道我自己是怎么打出这个字符的,我们的用户我也不知道他是怎么打出这个字符的,太神奇了!

 

如果你的程序对这种东西很敏感的话,建议把它过滤掉,但是经过我的实验,正则表达式的\s是无法过滤它的…

难怪编译器也把它当成源代码的一部分了…

本作品由 Dozer 创作,采用 知识共享署名-非商业性使用 4.0 国际许可协议 进行许可。