文件对比这个扩展现在用得比较少,因为大部分情况下我们都在使用一些代码管理工具,比如 Git 或者 Svn 之类的,其实它的作用就非常类似这类工具,另外还有一个非常常用的 Beyond Compare 工具也能方便地让我们能够进行文件的对比。

安装及准备工作

在 PHP 中的这个文件扩展叫做 xdiff 扩展,我们可以直接在 pecl 中下载并安装。

需要注意的是,安装这个扩展需要操作系统安装 libxdiff 工具,在文章最下方的参考链接中有这个工具的官网地址。libxdiff 无法使用默认的 yum 安装,所以需要下载之后自行安装。和其它的 Linux 工具一样,安装过程非常简单,这里就不多赘述了。

xdiff 扩展支持字符串和文件两种形式的差异对比以及一些相关的操作,这里我们以字符串的操作为主进行讲解,文件相关的操作将在最后给出全部的操作函数用法。首先,我们需要定义一些字符串以及相关的文件便于后续的操作。

$old_article = "我本无为野客,飘飘浪迹人间。
一时被命住名山。未免随机应变。
识破尘劳扰扰,何如乐取清闲。
流霞细酌咏诗篇。且与白云为伴。";
$new_article = "我本无为野客,飘飘浪迹人间。
一时被命住名山。未免随机应变。
识破尘劳扰扰,何如乐取清闲。一
流霞细酌咏诗篇。且与白云为伴。";
$new_article1 = "我本无为野客,飘飘浪迹人间。
一时被命住名山。未免随机应变。二
识破尘劳扰扰,何如乐取清闲。
流霞细酌咏诗篇。且与白云为伴。
三一四一"; file_put_contents('old_file.txt', $old_article);
file_put_contents('new_file.txt', $new_article);
file_put_contents('new_file1.txt', $new_article1);

字符串差别

$diff = xdiff_string_diff($old_article, $new_article);
var_dump($diff);
// string(273) "@@ -1,4 +1,4 @@
// 我本无为野客,飘飘浪迹人间。
// 一时被命住名山。未免随机应变。
// -识破尘劳扰扰,何如乐取清闲。
// +识破尘劳扰扰,何如乐取清闲。一
// 流霞细酌咏诗篇。且与白云为伴。
// \ No newline at end of file
// "

使用 xdiff_string_diff() 函数就可以获得两段字符串中的差异信息。可以看到它的内容结构和 Git 的文件差异对比返回的内容非常相似。像用 + 、 - 号表示的那一行的差异,我们只要使用过 Git 或 Svn 就一定不会陌生。

合并字符串

var_dump(xdiff_string_merge3($old_article, $new_article, $new_article1, $error));
// string(180) "我本无为野客,飘飘浪迹人间。
// 一时被命住名山。未免随机应变。
// 识破尘劳扰扰,何如乐取清闲。一
// 流霞细酌咏诗篇。且与白云为伴。"
var_dump($error); // NULL

xdiff_string_merge3() 函数用于将三个字符串合并到一起,也是类似于 Git 中的 merge 功能。不过这个函数需要三个字符串,但是通过测试我们发现只有第一个 \$new_article 和原始的 $old_article 合并成功了。第三个 $new_article1 并没有合并到最后返回的字符串中。关于这个函数的功能和实际的效果并不一致的问题并没有找到任何相关的参考资料,官方文档的介绍也非常地简单,所以如果大家如果有知道这个函数的真实具体情况的,可以留言一起讨论哦!

$error 参数是一个可选的引用参数,如果合并过程中出现任何问题它将返回错误信息。

修补数据(补丁)

var_dump(xdiff_string_patch($old_article, $diff, XDIFF_PATCH_NORMAL, $errors));
// string(180) "我本无为野客,飘飘浪迹人间。
// 一时被命住名山。未免随机应变。
// 识破尘劳扰扰,何如乐取清闲。一
// 流霞细酌咏诗篇。且与白云为伴。"
var_dump($errors); // NULL

从函数的名称中的 patch 就能看出,这个 xdiff_string_patch() 是为差异字符串打补丁用的。在曾经的桌面时代,不管是操作系统还是各种游戏,都经常会更新各种补丁。这里的补丁其实和合并差异比较类似。它的第一个参数是原始的字符串,第二个参数是 xdiff_string_diff() 生成的差异数据,打补丁的结果就是返回正式的全并差异之后的字符串。

第三个参数是可选的,它还可以定义成 XDIFF_PATCH_REVERSE ,也就是反转补丁,只返回原始的数据,不返回差异合并后的结果。反过来说,使用这个参数我们可以将第一个参数设置为修改后的 $new_article ,然后反转回原始的数据,大家可以自行尝试一下。最后的参数同样是可选的引用类型的错误变量。

二进制修补数据

$patchBinary = xdiff_string_bdiff($old_article, $new_article);
var_dump($patchBinary);
// string(44) "�{�N��一
// 流霞细酌�!" var_dump(xdiff_string_bdiff_size($patchBinary)); // int(180)
var_dump(xdiff_string_bpatch($old_article, $patchBinary));
// string(180) "我本无为野客,飘飘浪迹人间。
// 一时被命住名山。未免随机应变。
// 识破尘劳扰扰,何如乐取清闲。一
// 流霞细酌咏诗篇。且与白云为伴。"

除了原文的字符串操作之外,我们还可以使用 xdiff_string_bdiff() 返回二进制的字符串差异结果。同样地,使用 xdiff_string_bpatch() 可以对这个二进制的字符串操作结果打补丁,也就是合并差异。另外在二进制操作中还有一个函数 xdiff_string_bdiff_size() 用于返回二进制差异函数所返回的结果中的字符长度。

$raPatchBinary = xdiff_string_rabdiff($old_article, $new_article1);
var_dump($raPatchBinary);
// string(46) "�{�N�X二XY
// 三一四一" var_dump(xdiff_string_bdiff_size($raPatchBinary)); // int(193)
var_dump(xdiff_string_bpatch($old_article, $raPatchBinary));
// string(193) "我本无为野客,飘飘浪迹人间。
// 一时被命住名山。未免随机应变。二
// 识破尘劳扰扰,何如乐取清闲。
// 流霞细酌咏诗篇。且与白云为伴。
// 三一四一"

最后还有一个 xdiff_string_rabdiff() ,也是返回二进制的数据差异信息的。它和 xdiff_string_bdiff() 的区别主要是使用的算法不同。

文件操作

上面我们详细地介绍了 xdiff 扩展对于字符串的操作。它同时还提供了一系列的针对文件的操作,使用这些直接操作文件的函数就真的和我们的 Git 之类的工具非常类似了。

$old_file = 'old_file.txt';
$new_file = 'new_file.txt';
$new_file1 = 'new_file1.txt';
$diff_file = 'file.diff';
$merge_file = 'merge.txt';
$patch_file = 'patch.diff'; echo "File Diff: ", PHP_EOL;
$patch = xdiff_file_diff($old_file, $new_file, $diff_file);
var_dump($patch); // bool(true)
var_dump(file_get_contents($diff_file));
// string(273) "@@ -1,4 +1,4 @@
// 我本无为野客,飘飘浪迹人间。
// 一时被命住名山。未免随机应变。
// -识破尘劳扰扰,何如乐取清闲。
// +识破尘劳扰扰,何如乐取清闲。一
// 流霞细酌咏诗篇。且与白云为伴。
// \ No newline at end of file
// " echo 'File Merge: ', PHP_EOL;
var_dump(xdiff_file_merge3($old_file, $new_file, $new_file1, $merge_file));
// string(307) "@@ -1,4 +1,5 @@
// 我本无为野客,飘飘浪迹人间。
// -一时被命住名山。未免随机应变。
// +一时被命住名山。未免随机应变。二
// 识破尘劳扰扰,何如乐取清闲。
// -流霞细酌咏诗篇。且与白云为伴。+流霞细酌咏诗篇。且与白云为伴。
// +三一四一"
var_dump(file_get_contents($merge_file));
// string(180) "我本无为野客,飘飘浪迹人间。
// 一时被命住名山。未免随机应变。
// 识破尘劳扰扰,何如乐取清闲。一
// 流霞细酌咏诗篇。且与白云为伴。" echo "File Patch: ", PHP_EOL;
var_dump(xdiff_file_patch($old_file, $diff_file, $patch_file, XDIFF_PATCH_NORMAL)); // bool(true)
var_dump(file_get_contents($patch_file));
// string(180) "我本无为野客,飘飘浪迹人间。
// 一时被命住名山。未免随机应变。
// 识破尘劳扰扰,何如乐取清闲。一
// 流霞细酌咏诗篇。且与白云为伴。" echo "File Binary Diff: ", PHP_EOL;
$patchBinary = xdiff_file_bdiff($old_file, $new_file, $diff_file);
var_dump($patchBinary); // bool(true)
var_dump(file_get_contents($diff_file));
// string(44) "�{�N��一
// 流霞细酌�!" var_dump(xdiff_file_bdiff_size($diff_file)); // int(180)
var_dump(xdiff_file_bpatch($old_file,$patchBinary, $patch_file)); // bool(false)
var_dump(file_get_contents($patch_file));
// string(180) "我本无为野客,飘飘浪迹人间。
// 一时被命住名山。未免随机应变。
// 识破尘劳扰扰,何如乐取清闲。一
// 流霞细酌咏诗篇。且与白云为伴。" echo "File RA Binary Diff: ", PHP_EOL;
$raPatchBinary = xdiff_file_rabdiff($old_file, $new_file1, $diff_file);
var_dump($raPatchBinary); // bool(true)
var_dump(file_get_contents($diff_file));
// string(46) "�{�N�X二XY
// 三一四一" var_dump(xdiff_file_bdiff_size($diff_file)); // int(193)
var_dump(xdiff_file_bpatch($old_file, $raPatchBinary, $patch_file)); // bool(false)
var_dump(file_get_contents($patch_file));
// string(193) "我本无为野客,飘飘浪迹人间。
// 一时被命住名山。未免随机应变。二
// 识破尘劳扰扰,何如乐取清闲。
// 流霞细酌咏诗篇。且与白云为伴。
// 三一四一"

这里我们就不一一讲解了,这些函数的操作和功能与字符串操作的相关函数都是类似的,只是参数略有不同。比如它们在对比或者合并、补丁之后都会生成一个文件,所有函数的参数都是以文件为基础的。大家可以自行运行一下测试代码并参考官方文档进行学习。

总结

关于这个 xdiff 扩展其实我们使用得并不多,不过曾经看过有一套开源的使用 PHP 来做的 CMS 系统中管理前端模板页面的功能中就使用到了这一套扩展。任何工具的存在都有它的意义,或许你在为某个功能而苦恼的时候正好就看到了这篇文章,从而轻松地解决了手头上的问题也说不准,了解并有个大概的印象,在工作中才不至于摸瞎,这就是我们刷文档的意义。

测试代码:

https://github.com/zhangyue0503/dev-blog/blob/master/php/202010/source/10.PHP中的文件对比扩展.php

参考文档:

https://www.php.net/manual/zh/book.xdiff.php

https://directory.fsf.org/wiki/LibXDiff

关注公众号:【硬核项目经理】获取最新文章

添加微信/QQ好友:【xiaoyuezigonggong/149844827】免费得PHP、项目管理学习资料

知乎、公众号、抖音、头条搜索【硬核项目经理】

B站ID:482780532

PHP中的文件对比扩展的更多相关文章

  1. 在PHP中操作文件的扩展属性

    在操作系统的文件中,还存在着一种我们可以自己定义的文件属性.这些属性不是保存在文件内容中,也不是直接可以通过 ls -al 所能看到的内容.它们可以将一个键值对信息永久得关联到文件上,一般现在的 Li ...

  2. 从一个标准URL中提取文件的扩展名

    例如:http://www.sina.cn/abc/de.php?id=1  提出php 1. $url = 'http://www.sina.cn/abc/de.php?id=1'; $arr = ...

  3. 获取URL中的文件的扩展名

    问题: 尽可能多地写出获取文件扩展名的方法: //方法一(分割数组) function getExt($url){ $arr = explode('.',$url); $len = count($ar ...

  4. PHP中获取文件扩展名

    function get_extension($file) { return substr(strrchr($file, '.'), 1) ; } function get_extension($fi ...

  5. C#路径中获取文件全路径、目录、扩展名、文件名称

    C#路径中获取文件全路径.目录.扩展名.文件名称常用函数 需要引用System.IO 直接可以调用Path的静态方法 class Program { static void Main(string[] ...

  6. C# 选择文件、选择文件夹、打开文件(或者文件夹) 路径中获取文件全路径、目录、扩展名、文件名称 追加、拷贝、删除、移动文件、创建目录 修改文件名、文件夹名!!

    https://www.cnblogs.com/zhlziliaoku/p/5241097.html 1.选择文件用OpenDialog OpenFileDialog dialog = new Ope ...

  7. PHP中获取文件扩展名的N种方法

    PHP中获取文件扩展名的N种方法 从网上收罗的,基本上就以下这几种方式: 第1种方法:function get_extension($file){substr(strrchr($file, '.'), ...

  8. 三、Linux系统中的文件类型和文件扩展名

    .sock文件也是一类特殊的文件,这类文件通常用在网络之间进行数据连接,如:我们可以启动一个程序来监听客户端的要求,客户端可以通过套接字来进行通信: linux中的文件类型 文件类型介绍 Linux系 ...

  9. 【转】C#路径中获取文件全路径、目录、扩展名、文件名称

    C#路径中获取文件全路径.目录.扩展名.文件名称 原文链接:https://www.cnblogs.com/JiYF/p/6879139.html 常用函数 需要引用System.IO   直接可以调 ...

随机推荐

  1. DDD领域驱动理解

    在理解领域驱动的时候,网上很多大谈理论的文章,这种对于初学者不是太容易接受.根据我自己的学习经历,建议按照如下几个步骤学习: 粗略的看一遍领域驱动的理论,做到心中有形,知道领域驱动是什么,解决什么问题 ...

  2. 初探 Python Flask+Jinja2 SSTI

    初探 Python Flask+Jinja2 SSTI 文章首发安全客:https://www.anquanke.com/post/id/226900 SSTI简介 SSTI主要是因为某些语言的框架中 ...

  3. Linux添加防火墙、iptables的安装和配置

    由于centos7默认是使用firewall作为防火墙,下面介绍如何将系统的防火墙设置为iptables. #停止firewall systemctl stop firewall.service #禁 ...

  4. jsoup的Document类

    一.简介 Document是一个装载html的文档类,它是jsoup一个非常重要的类.类声明:public class Document extends Element .Document是Node间 ...

  5. C++ 三数之和

    来自leecode做题时,发现的双指针用法,觉得挺有意思所以记录一下 链接:https://leetcode-cn.com/problems/3sum 题目: 给你一个包含 n 个整数的数组 nums ...

  6. Spring详解(十)------spring 环境切换

    软件开发过程一般涉及"开发 -> 测试 -> 部署上线"多个阶段,每个阶段的环境的配置参数会有不同,如数据源,文件路径等.为避免每次切换环境时都要进行参数配置等繁琐的操 ...

  7. 面向对象之编写驱动程序--中断(linux系统、s3c6410开发板)

    /*------------------------- *先申明下,本人是个菜鸟,刚开始接触驱动程序编写,交代下开发环境(主机系统redhat6.3,开发板ARM-s3c6410) 以watchdog ...

  8. Mybatis--级联(一)

    级联是resultMap中的配置. 级联分为3种 鉴别器(discrimination):根据某些条件采用具体实现具体实现类级联,如体检表根据性别去区分 一对一:学生和学生证 一对多:班主任和学生. ...

  9. JDBC基础篇(MYSQL)——使用CallabeStatement调用存储过程

    注意:其中的JdbcUtil是我自定义的连接工具类:代码例子链接: package day04_callable; import java.sql.CallableStatement; import ...

  10. HTML5存储 ——Web Storage(localStorage 和 sessionStorage)

    一.localStorage对象临时储存API 方法: 1.localStorage.setItem(key,value)---设置存储内容 2.localStorage.getItem(key)-- ...