乐趣区

关于java:艺术鬼才Unicode-字符还能这么玩

上周的时候,朋友圈的直升飞机不晓得为什么就火了,很多敌人开着各种花式飞机带着腾飞。

还没来得及理解咋回事来着,这个直升飞机就???? 到的微博热搜。

前面越来越多人开来他们的直升飞机,回旋在朋友圈上方。于是很多敌人开来他们的坦克,专打直升飞机,一轰一个准。

好了,说回正题!

程序员敌人应该都很相熟 Unicode(万国码),它简直蕴含世界上所有符号,比方组成直升飞机这几个特殊符号对应的 Unicode 码别离为:

ps: 举荐一个网站,能够依据符号搜对应的 Unicode 码:https://unicode.yunser.com/un…

除了这些失常字符以外,Unicode 还蕴含着各种各样的奇葩字符。

奇葩字符

除了失常的咱们熟知的文字以外,Unicode 中还有一些奇怪的文字,比方上面这些文字

除了这些奇怪文字以外,Unicode 还有一些奇葩的的符号。

例如上面一整套麻将牌:

一整套的扑克牌:

一整套国际象棋:

除了这些,通过组合合乎,咱们还能够造出各种各样的颜文字(๑•̀ㅂ•́)و✧、

另外 Unicode 还收录着咱们罕用的 Emoji

除了这些之外,Unicode 中还有一些特殊字符的,利用这些字符,咱们还能够玩出很多乏味的骚操作。

组合字符

Unicode 有一类字符称为组合字符,它能够附加在前一个非组合字符上,从而使整体看起来像是一个字符。

组合字符原来目标是为了解决一些地区语言、文字非凡的须要,比如说泰文腔调符号与母音符号。

失常应用的状况下,这些组合字符数量都会有一些限度。然而在 Unicode 组合字符设计上,并没有加这种限度,这样使咱们能够有限加这类组合字符。

利用这个个性,能够达到一些恶搞成果,比方「击穿天花板」与「凿穿地板」的成果。

下面实现原理其是利用以下两个组合字符:

只有复制这两个字符相应的 HTML 代码,跟在失常的字符前面,就能够使这两个字符附加在一般字符上,比方上面实现成果为

黑 ̮̑

Unicode 码值通常应用 U+N(16 进制 N 代表码值),比方 A 的码值为 U+0041。

在 HTML 中 Unicode 能够应用 &#N;(十进制,N 代表码值)示意

在 JS 中 Unicode 中须要应用] \uN(16 进制 N 代表码值)示意

只有咱们在一般字符多复制几个这类附加字符,就能够造成上述「击穿」成果。

还记得下面说的泰文吗,已经有一段时间贴吧,很风行一种喷射文,比方上面的成果。

这种喷射文理论原理就是利用泰文中腔调符号附加在其余失常符号上。

不过当初这个成果貌似曾经没方法再复现了,当初咱们只能看到这样的成果:

在一些老版本的零碎 / 浏览器可能还能看到这种成果,晓得的小伙伴留言区能够告知一下。

零宽字符

Unicode 中还有一类格局字符,不可见,不可打印,次要作用于调整字符的显示格局,所以咱们将其称为零宽字符。

零宽字符次要有以下几类:

零宽度空格符 (zero-width space) U+200B : 用于较长单词的换行分隔

零宽度非断空格符 (zero width no-break space) U+FEFF : 用于阻止特定地位的换行分隔

零宽度连字符 (zero-width joiner) U+200D : 用于阿拉伯文与印度语系等文字中,使不会产生连字的字符间产生连字成果

零宽度断字符 (zero-width non-joiner) U+200C : 用于阿拉伯文,德文,印度语系等文字中,阻止会产生连字的字符间的连字成果

左至右符 (left-to-right mark) U+200E : 用于在混合文字方向的多种语言文本中(例:混合左至右书写的英语与右至左书写的希伯来语),规定排版文字书写方向为左至右

右至左符 (right-to-left mark) U+200F : 用于在混合文字方向的多种语言文本中,规定排版文字书写方向为右至左

利用零宽字符不不可见的个性,咱们也能够玩出一些骚成果。

空白微博

公布微博的时候,如果内容都是空格,将没方法公布。

然而如果咱们将零宽字符,比如说「零宽度空格符 U+200B」复制到微博,这样咱们就能够公布空白微博。

咱们能够利用 Chrome 浏览器的控制台复制零宽字符,操作形式如下:

公布成果如下:

隐形水印

对于一些外部论坛或者说小说网站来说,能够通过零宽字符在帖子或小说内容嵌入隐形水印。

当这些内容被一些爬虫复制到其余网站时,咱们就能够通过隐形水印,轻松查找时那位用户透露内容。

隐形水印 次要原理 就是将用户信息比方用户名,通过肯定算法转成零宽字符,这样普通用户浏览时齐全看不到这个水印。

如果内容被复制到其余网站,隐形谁赢也被复制,只有找到这个水印,将这些零宽字符反转成用户名即可。

上面展现一种转换方法,JS 代码次要参考以下 Github 我的项目:

https://github.com/umpox/zero…

隐形水印生成办法

第一步咱们须要将明文字符串每个字符都转成二进制串。

    // 每个字符转为二进制, 用空格分隔
    const textToBinary = username => (
      username
      .split('')
      // charCodeAt 将字符转成相应的 Unicode 码值
      .map(char => char.charCodeAt(0).toString(2))
      .join(' ')
    );

示例如下:

第二步,将二进制串转为零度字符串,转换规则如下:

  • 1 转换为 u200b 零宽度字符(zero-width space)
  • 0 转换为 u200c 零宽度断字符(zero-width non-joiner)
  • 其余(残余就是空格)转换为 u200d 零宽度连字符 (zero-width joiner)
  • 最初应用 ufeff 零宽度非断空格符 (zero width no-break space) 作为分隔符
const binaryToZeroWidth = binary => (binary.split('').map((binaryNum) => {const num = parseInt(binaryNum, 10);
    if (num === 1) {return '\u200b'; // \u200b 零宽度字符(zero-width space)} else if(num===0) {return '\u200c'; // \u200c 零宽度断字符(zero-width non-joiner)}
    return '\u200d'; // \u200d 零宽度连字符 (zero-width joiner)

  }).join('\ufeff') // \ufeff 零宽度非断空格符 (zero width no-break space)
);

最终加密办法如下:

const encode = username => {const binaryUsername = textToBinary(username);
  const zeroWidthUsername = binaryToZeroWidth(binaryUsername);
  return zeroWidthUsername;
};

应用加密办法将明文字符串加密之后,加密字符串肉眼是看不到了,然而理论还是存在的。

实际上,如果咱们将加密之后字符串复制到 BEJSON 网站, 就能够看到字符。

另外你还能够把加密字符串复制到 IDEA 中,能够看到相应的 Unicode 编码值。

解密隐形水印

晓得了加密的形式,解密其实就很简略,咱们只有依照相同步骤的来就能够了。

第一步,将隐形水印依照以下规定转换为二进制串。转换规则如下:

  • 应用 ufeff 分隔字符串
  • u200b 转为 1
  • u200c 转为 0
  • 其余字符应用空格
const zeroWidthToBinary = string => (string.split('\ufeff').map((char) => {// \ufeff 零宽度非断空格符 (zero width no-break space)
    if (char === '\u200b') { // \u200b 零宽度字符(zero-width space)return '1';
    } else if(char === '\u200c') { // \u200c 零宽度断字符(zero-width non-joiner)return '0';
    }
    return ' ';
  }).join('')
);

调用该办法,隐形水印转成二进制串。

第二步,将二进制再转为相应的字符。

const binaryToText = string => (
  // fromCharCode 二进制转化
  string.split('').map(num => String.fromCharCode(parseInt(num, 2))).join('')
);

最终解密办法如下:

const decode = zeroWidthUsername => {const binaryUsername = zeroWidthToBinary(zeroWidthUsername);
  const textUsername = binaryToText(binaryUsername);
  return textUsername;
};

解密示例如下:

短网址

咱们罕用的短网址,域名前面会跟上一串随机串,从而实现短网址到长网址的映射。比方以下网址:

https://sourl.cn/iLyn9S

然而咱们能够利用零宽字符也能够实现短网址的成果,, 比方上面这个网站,就能够生成这类短网址。

https://zws.im/

能够看到这个短网址前面看不到任何字符,实际上这前面跟着一串零宽字符。当浏览器拜访该短网址时,后端程序只有反解密的前面零宽字符,拿到相应的网址,而后在做跳转就能够到指定的网站。

反解密的原理能够参考下面隐形水印的代码

小心零宽字符

日常开发过程中,咱们有时须要从一些文件中读取文本内容,而后做相应的解决。

有时候咱们可能会碰到一些诡异的景象,比方咱们之前碰到的例子。

后台程序从 Excel 读取文本内容,而后程序中判断是读取的文本内容是否与指定的字符串相等。

而后当咱们读取一份 Excel 内容后,返现这段比拟逻辑怎么也通过不了。原本认为是 Excel 内容存在空格什么的,然而关上 Excel 认真一看,跟指定字符串截然不同,并没有什么其余字符。

第一次碰到这种例子,没有什么教训,真的排查了很久,到最初都有点狐疑人生了。最初无意间将文本内容复制到了 IDEA 中,才发现整顿混杂着零宽字符!

如果各位小伙伴也碰到这类问题,无妨将复制文本内容,而后到 IDEA 中查看是否存在某些看不见字符~

最初(点个赞呗!)

这两个星期始终很忙,始终都在 9106 的节奏,真的是累,所以断更了一周!

所幸最近我的项目提测,略微轻松了一点,能有点划水工夫来写写文章。不过再提起笔来写文章,就有点断节奏了!

这篇文章墨迹了很久才水进去,下周开始再次复原周更的节奏,再忙再累,每周都来一篇。

欢送各位小伙伴,每周来这里蹲我,Gank 我!!!

好了,我是楼下小黑哥,下周见!!!

参考链接

  1. https://juejin.im/post/5d3f01…
  2. http://zero.rovelast.com/
  3. https://zws.im/
  4. https://imweb.io/topic/5a08a5…

欢送关注我的公众号:程序通事,取得日常干货推送。如果您对我的专题内容感兴趣,也能够关注我的博客:studyidea.cn

退出移动版