0x00 前言

第一次遇见字符串这个概念是在学 C 语言的时候,那时候觉得字符串也没有什么难的,不就是一个以 \0 结尾的 char 数组而已咯。后来在学习 PHP 的过程中也同样保持这个观念,不过在字符串还是纯英文的时候还是没什么问题的,但后面遇到要处理中文的时候就事故频发,然后搜索结果里的字符集字符编码多字节字符串二进制安全各种概念搞得一头雾水,虽然最后的搜索结果都附有了解决方案但我还是觉得对于相关的知识需要理解和总结。

0x01 字符集

字符集(全称是编码字符集)是一个系统支持的所有抽象字符的集合。字符是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等。字符集都可以用「一张或多张二维表」表示,比如:ASCII 是很常见的一个字符集,一提起它我们应该都能想到下面这张图。我们可以看见每一个字符都对应有一个二进制编码

因为ASCII 字符集上的编码和字符编码是一样的,然后很多刚学习的人就把字符集和字符编码给弄混淆了。但是实际上字符集和字符编码是不同的概念

0x02 字符编码

由于历史原因,在早期字符集其实和字符编码是同义的,因为字符集的编码就是对应字符实际储存的值,直到 Unicode 的出现,因为 Unicode 有好几种不同的字符编码,比如:UTF-8UFF-16UTF-32。然后字符编码的概念就出来了,字符编码是字符集和实际存储数值之间的转换关系,也就是说字符编码是定义在字符集上的映射规则。然后我就开始有点头晕了/(ㄒoㄒ)/~~,字符编码 UTF-8 和字符集 Unicode 到底是什么关系?

实际上我们可以说UTF-8 是 Unicode 的一种实现方式云服务器Window Server 2012R系统安装MySQL的详细教程

我们可以查到在 Unicode 码表中,「国」字对应的十六进制编码是 0x56FD 但是如果我们新建一个文本文件,输入一个「国」字并用 UTF-8 的字符编码储存,然后以十六进制的方式查看该文件,我们会发现储存的并不是 0x56FD 而是 0xE59BBD。因为字符集的编码通过某种规则转换为了实际存储的数据,这里的某种规则即是字符编码。下面一图可以看出字符集和字符编码的不同。

既然字符集已经有编码了(而且很多字符集的字符编码和字符集上的编码一样),那为何要多此一举搞个字符编码出来?因为如果直接采用字符集上的编码,那么像 Unicode 之类的字符集,它的每个字符都需要三个字节储存,而对于一些常见的字符(比如:英文字母)来说用三个字节储存无疑是很浪费空间的。而通过 UTF-8 字符编码便可以将常见的字符采用较少的字节编码,而不常用的字符就采用较多的字节编码,达到节约储存空间的目的。

0x03 多字节字符串

PHP 在处理非英文的字符串时,部分字符串相关的函数可能会经常出现问题,因为 PHP 中处理字符串的函数默认假设所有字符都是 8 位字符,占用一个字节。而中文至少要用两个或三个字节储存(使用 UTF-8 编码),所以经常会出错。比如 strlen 函数在测试中文字符串时得到的是字节长度而不字符长度,所以我们应该利用 mbstring 拓展 提供的多字节字符串函数进行处理。

0x04 二进制安全

在浏览字符串处理函数的过程中我们常常会看到一个词「二进制安全」,听着感觉很高大上的样子然后网上对它的解释如下:

二进制安全是一个主要用来处理字符串操作的编程术语。二进制安全功能本质上是把输入当作一个没有任何特殊的原生流,其在操作上应包含一个字符所能有的256种可能的值(假设为8为字符)。

听着有点似懂非懂的样子,但和 C 语言的字符串作对比之后就比较明白了。

C 字符串中的字符必须符合某种编码(比如 ASCII),并且除了字符串的末尾之外,字符串里面不能包含空字符,否则最先被程序读入的空字符将被误认为是字符串结尾 ——这些限制使得 C 字符串只能保存文本数据,而不能保存像图片、音频、视频、压缩文件这样的二进制数据。

也就是说在二进制安全的函数操作里 \0 并不会看做字符串的结尾,字符串中所有的数据都没有特殊的含义。所以 PHP 的 strlen 函数能获取包含空字符的字符串长度,而 C 语言却不行。当然 PHP 里也有非二进制安全的函数,所以在使用某些函数前还是要注意函数是否是二进制安全的。如下例:

<?php
$str1 = "good";
$str2 = "good\0bad";
var_dump(strcoll($str1, $str2));
// 非二进制安全,输出 0
var_dump(strcmp($str1, $str2));
// 二进制安全,输出 -4

  

写这篇文章的时候真的觉得很难写( ⊙ o ⊙ )啊!感觉自己还是说的不清不楚的样子,还没有网上的资料讲得好。但进行一下总结起码能够加强记忆吧/(ㄒoㄒ)/~~。有错的地方希望有人能够提出来(但我觉得应该都不会有人来看我的博客的233,更不会有评论)。0x05 总结

0x06 参考资料

十分钟搞清字符集和字符编码

字符集和字符编码

字符,字符集,字符编码解惑

PHP 的二进制安全

文章转自:https://www.0php.net/posts/PHP-字符串相关常识.html

PHP 字符串相关常识的更多相关文章

  1. 常用linux 命令 -字符串相关

    参考网络文章,个人工作总结 题记:一般对字符串的操作有以下几种:求长度,截取字符串,拼接字符串,找字符串中某个字符的索引 1 expr 命令 1.1 定义 man 手册 Print the value ...

  2. 【Todo】字符串相关的各种算法,以及用到的各种数据结构,包括前缀树后缀树等各种树

    另开一文分析字符串相关的各种算法,以及用到的各种数据结构,包括前缀树后缀树等各种树. 先来一个汇总, 算法: 本文中提到的字符串匹配算法有:KMP, BM, Horspool, Sunday, BF, ...

  3. python中跟字符串相关的一些操作

    公司让用python自动生成代码,以前没看过python.所以匆匆的看了两天python就连猜带蒙就上马开干了..因此好多操作可能看的时候看懂了,用的时候知道有这么个东西,具体用法就忘记了..用到了就 ...

  4. IP相关常识

    IP相关常识 一.  IP地址概念 IP地址是一个32位的二进制数,它由网络ID和主机ID两部份组成,用来在网络中唯一的标识的一台计算机.网络ID用来标识计算机所处的网段:主机ID用来标识计算机在网段 ...

  5. ES6字符串相关扩展

    变量的解构赋值 // 数组的解构赋值 let [a,b,c] = [1,2,3]; //1,2,3 let [a,b,c] = [,123,]; //undefined 123 undefined l ...

  6. Java数据结构和算法总结-字符串相关高频面试题算法

    前言:周末闲来无事,看了看字符串相关算法的讲解视频,收货颇丰,跟着视频讲解简单做了一下笔记,方便以后翻阅复习同时也很乐意分享给大家.什么字符串在算法中有多重要之类的大路边上的客套话就不多说了,直接上笔 ...

  7. PHP基础系列(一) PHP字符串相关的函数分类整理

    PHP提供了非常丰富的自带函数,有人说PHP是一个大的函数库,在某种程度上我是非常认同这种观点的,这个也是PHP非常容易上手的原因之一.在使用PHP编程的时候,需要实现某一功能的时候,如果说php自带 ...

  8. python字符串、字符串处理函数及字符串相关操作

    python字符串.字符串处理函数及字符串相关操作 字符串介绍 python字符串表示 Python除处理数字外还可以处理字符串,字符串用单撇号或双撇号包裹: >>> 'spam e ...

  9. java常用类详细介绍及总结:字符串相关类、日期时间API、比较器接口、System、Math、BigInteger与BigDecimal

    一.字符串相关的类 1.String及常用方法 1.1 String的特性 String:字符串,使用一对""引起来表示. String声明为final的,不可被继承 String ...

随机推荐

  1. 爬虫4之pyquery

    pyquery 初始化 字符串初始化 from pyquery import PyQuery as pq doc = pq(html)#html为需要处理的内容 #方法与CSS选择器相同 print( ...

  2. kettle学习资料

    1.kettle资源丰富:kettle中文网 http://www.kettle.net.cn/category/use?tdsourcetag=s_pctim_aiomsg

  3. 【VS开发】raw socket 的例子

    raw socket 的例子 一. 摘要    Raw Socket: 原始套接字    可以用它来发送和接收 IP 层以上的原始数据包, 如 ICMP, TCP, UDP... int sockRa ...

  4. maven 报错 -source 1.5 中不支持 diamond 运算符

    maven 执行install 报-source 1.5 中不支持 diamond 运算符 解决办法, 指定编译版本 <build> <plugins> <plugin& ...

  5. Python的入门(day1)

    一:Python的起源 Python的创始人为Guido van Rossum.1989年圣诞节期间,在阿姆斯特丹,Guido为了打发圣诞节的无趣,决心开发一个新的脚本解释程序,做为ABC 语言的一种 ...

  6. Hbase的几个关键问题(转自log.csdn.net/javastart/article/details/43772575)

    什么是HBase?何时用HBase?与Hive.Pig的区别?HBase的结构为何HBase速度很快?HBase常用的操作有哪些?HBase的一些配置和监控 什么是HBase? HBase,是Hado ...

  7. $Prufer$序列

    \(Prufer\)序列 \(Prufer\)序列与树的相互转换: 树->\(Prufer\)序列 找到一个编号最小的叶子结点,把这个点删掉并且把跟他连着的那个点的编号加入\(Prufer\)序 ...

  8. P1397 [NOI2013]矩阵游戏

    传送门 首先显然可以矩乘快速幂然后 $T$ 飞 看一眼题解发现因为这一题矩阵的特殊性所以可以对矩阵的次数欧拉降幂 然而我并不懂证明,所以我选择暴力乱搞的做法 十进制快速幂,然后注意一下常数,还有矩阵乘 ...

  9. P多行溢出省略号的处理

    因为-webkit-line-clamp: 2不兼容火狐或IE,采用判断浏览器的方式来启用哪个方式 先判断是什么浏览器 //判断是否是谷歌浏览器 if (!stripos($_SERVER[" ...

  10. element-ui 中 switch 开关绑定number 的解决方法

    虽然element-ui 的文档中说明 v-model的值可以是 boolean / string / number 三种类型 , (文档在此)https://element.eleme.cn/#/z ...