字符集和编码简介
当文档显示在屏幕上时,人类将它们解析为字符序列(在计算机文本处理的上下文中也称为字形)。但是,当文档存储在磁盘上时,它们被写入字节序列,就像所有其他类型的文件一样。因此,必须有一个系统负责将字符转换为字节,反之亦然。
这样的系统称为字符编码。由于编码必须由计算机实现,因此它们需要明确定义,因此每种编码只能处理一组预定义的字符,这毫不奇怪称为字符集。
一些编码总是用一个字节来表示每个字符;这些被称为单字节编码。其他编码对每个字符使用多个字节,而不一定对所有可能的字符使用相同的数字;这些被称为多字节编码。
回顾一下:一个文本文档在逻辑上包含从一些预定义字符集中提取的字符,但是计算机以字节为单位工作,因此我们组成了将字符转换为字节的字符编码,反之亦然。一些编码被称为多字节,因为它们使用多个字节来表示单个字符。
回到你的问题
当您将文本文件保存到磁盘时,记事本使用了某种编码(这是一种多字节编码,但我们暂时假设我们不知道)。文本中的字符¬
以字节的形式给出了一些特定的表示。
当您将 PHP 文件保存到磁盘时,您的源代码编辑器使用了一些编码来执行此操作。字符串文字 '/¬/' 中的字符¬
以字节的形式给出了一些特定的表示。
默认情况下preg_replace
,就像 PHP 中的所有通用字符串函数一样,以二进制模式运行。这意味着它以字节为单位工作。这与您的源代码编辑器形成对比,后者具有编码意识并以字符的形式显示源代码。结果,当您替换您认为是字符¬
(NOT SIGN)时,preg_replace
实际上替换了一系列字节,其确切形式取决于您的 PHP 源代码的编码。
这就是问题所在:如果文本文件的编码与您的源代码不匹配,那么所有关于文本可能实际发生的事情的赌注都将落空。
鉴于您显示的结果,您的情况很可能是这样的:
- 文本文件以某种多字节编码保存。
- PHP 源代码以单字节编码保存。
¬
PHP 源代码中的单字节表示¬
是文本中多字节表示的一部分,因此其中一个字节被删除了。
- 剩余的字节不符合编码规则,因此在替换后显示文本的程序会显示一个问号,表示“这里有东西,但不是我识别的字符”。
如何修复它
几种可能性都与上述一致,但它们都有一个共同的属性:您必须知道文本文件的编码(您可以使用记事本轻松做到这一点:“另存为”并查看对话框底部)。那么你也能:
- 使用相同的编码保存您的文本文件和 PHP 源代码,一切都会正常工作。这是迄今为止最简单的。
将表示文本文件编码中目标字符的字节注入您的 PHP 源代码。例如,假设文本文件保存为 UTF-8。此编码用字节序列 0xC2 0xA2 表示有问题的字符,因此您可以通过将代码编写为来替换此字节序列
preg_replace("/\xc2\xa2/", '', $string)
并且只要文本文件编码保持 UTF-8,无论您的 PHP 源代码是什么编码,它都可以工作。