如何删除多个 UTF-8 BOM 序列

使用 PHP5(cgi)从文件系统输出模板文件,并且在输出原始 HTML 时遇到问题。

private function fetch($name) {
$path = $this->j->config['template_path'] . $name . '.html';
if (!file_exists($path)) {
dbgerror('Could not find the template "' . $name . '" in ' . $path);
}
$f = fopen($path, 'r');
$t = fread($f, filesize($path));
fclose($f);
if (substr($t, 0, 3) == b'\xef\xbb\xbf') {
$t = substr($t, 3);
}
return $t;
}

尽管我已经添加了 BOM 修复程序,但 Firefox 接受它仍然存在问题。你可以在这里看到一个实时拷贝: http://ircb.in/jisti/(如果你想查看的话,还有我扔给 http://ircb.in/jisti/home.html的模板文件)

知道怎么解决吗

90644 次浏览

b'\xef\xbb\xbf'表示字符串“ xef xbb xbf”。如果要检查 BOM,则需要使用双引号,因此 \x序列实际上被解释为字节:

"\xef\xbb\xbf"

你的文件似乎也包含了更多的垃圾,而不仅仅是一个单一的 BOM:

$ curl http://ircb.in/jisti/ | xxd


0000000: efbb bfef bbbf efbb bfef bbbf efbb bfef  ................
0000010: bbbf efbb bf3c 2144 4f43 5459 5045 2068  .....<!DOCTYPE h
0000020: 746d 6c3e 0a3c 6874 6d6c 3e0a 3c68 6561  tml>.<html>.<hea
...

您将使用以下代码删除 utf8炸弹

//Remove UTF8 Bom


function remove_utf8_bom($text)
{
$bom = pack('H*','EFBBBF');
$text = preg_replace("/^$bom/", '', $text);
return $text;
}

尝试:

// -------- read the file-content ----
$str = file_get_contents($source_file);


// -------- remove the utf-8 BOM ----
$str = str_replace("\xEF\xBB\xBF",'',$str);


// -------- get the Object from JSON ----
$obj = json_decode($str);

:)

另一种移除物料 Unicode字符的方法是 u + FEFF

$str = preg_replace('/\x{FEFF}/u', '', $file);

此全局函数解析为 UTF-8系统基本字符集。坦克!

function prepareCharset($str) {


// set default encode
mb_internal_encoding('UTF-8');


// pre filter
if (empty($str)) {
return $str;
}


// get charset
$charset = mb_detect_encoding($str, array('ISO-8859-1', 'UTF-8', 'ASCII'));


if (stristr($charset, 'utf') || stristr($charset, 'iso')) {
$str = iconv('ISO-8859-1', 'UTF-8//TRANSLIT', utf8_decode($str));
} else {
$str = mb_convert_encoding($str, 'UTF-8', 'UTF-8');
}


// remove BOM
$str = urldecode(str_replace("%C2%81", '', urlencode($str)));


// prepare string
return $str;
}

做同样工作的另一种方法:

function remove_utf8_bom_head($text) {
if(substr(bin2hex($text), 0, 6) === 'efbbbf') {
$text = substr($text, 3);
}
return $text;
}

我找到的其他方法在我的情况下不起作用。

希望对特殊情况有帮助。

如果你正在使用 file_get_contents读取一些 API,并且从 json_decode得到一个无法解释的 NULL,检查 json_last_error()的值: 有时候从 file_get_contents返回的值会有一个无关的 BOM,当你检查字符串时几乎看不到,但是会使 json_last_error()返回 JSON_ERROR_SYNTAX(4)。

>>> $json = file_get_contents("http://api-guiaserv.seade.gov.br/v1/orgao/all");
=> "\t{"orgao":[{"Nome":"Tribunal de Justi\u00e7a","ID_Orgao":"59","Condicao":"1"}, ...]}"
>>> json_decode($json);
=> null
>>>

在这种情况下,检查前3个字节-回显它们不是很有用,因为 BOM 在大多数设置中是不可见的:

>>> substr($json, 0, 3)
=> "  "
>>> substr($json, 0, 3) == pack('H*','EFBBBF');
=> true
>>>

如果上面的代码行为您返回 TRUE,那么一个简单的测试可以解决这个问题:

>>> json_decode($json[0] == "{" ? $json : substr($json, 3))
=> {#204
+"orgao": [
{#203
+"Nome": "Tribunal de Justiça",
+"ID_Orgao": "59",
+"Condicao": "1",
},
],
...
}

如果有人使用 csv 导入,那么下面的代码很有用

$header = fgetcsv($handle);
foreach($header as $key=> $val) {
$bom = pack('H*','EFBBBF');
$val = preg_replace("/^$bom/", '', $val);
$header[$key] = $val;
}

没有 pack功能的解决方案:

$a = "1";
var_dump($a); // string(4) "1"


function deleteBom($text)
{
return preg_replace("/^\xEF\xBB\xBF/", '', $text);
}


var_dump(deleteBom($a)); // string(1) "1"

当使用有缺陷的软件时,BOM 部分会随着每次节省而成倍增加。

所以我要用这个来摆脱它。

function remove_utf8_bom($text) {
$bom = pack('H*','EFBBBF');
while (preg_match("/^$bom/", $text)) {
$text = preg_replace("/^$bom/", '', $text);
}
return $text;
}

我不太喜欢用 preg_replace或者 preg_match来完成简单的任务。这种检测和移除 BOM 的替代方法怎么样?

function remove_utf8_bom(string $text): string
{
$bomStart = mb_substr($text, 0, 1);
return ($bomStart == pack('H*','EFBBBF')) ?
mb_substr($text, 1) :
$text;
}

这样吧:

  function removeUTF8BomHeader($data) {
if (substr($data, 0, 3) == pack('CCC', 0xef, 0xbb, 0xbf)) {
$data = substr($data, 3);
}


return $data;
}

测试了很多,它的工作完美,没有任何问题