文件对比这个扩展现在用得比较少,因为大部分情况下我们都在使用一些代码管理工具,比如 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. IP笔记

    自动专用IP地址APIPA的范围是B类地址块169.254.0.0--169.254.255.255

  2. 程序员作图工具和技巧,你 get 了么?

    分享程序员常用的画图软件和小技巧 大家好,我是鱼皮. 说实话,我觉得做个程序员挺好的.日常工作有很多,写代码.对需求.写方案等等,但我最爱画图:流程图.架构图.交互图.功能模块图.UML 类图.部署图 ...

  3. 从自旋锁、睡眠锁、读写锁到 Linux RCU 机制讲解

    ​    同步自我的 csdn 博客 6.S081 从自旋锁.睡眠锁.读写锁到 Linux RCU 机制讲解_我说我谁呢 --CSDN博客 总结一下 O/S 课程里面和锁相关的内容. 本文是 6.S0 ...

  4. idea中使用docker插件部署项目

    安装docker 如果你之前安装过 docker,请先删掉 sudo yum remove docker docker-common docker-selinux docker-engine 安装一些 ...

  5. 第12篇-认识CodeletMark

    InterpreterCodelet依赖CodeletMark完成自动创建和初始化.CodeletMark继承自ResourceMark,允许自动析构,执行的主要操作就是,会按照Interpreter ...

  6. 最短路径 | 深入浅出Dijkstra算法(一)

    参考网址: https://www.jianshu.com/p/8b3cdca55dc0 写在前面: 上次我们介绍了神奇的只有五行的 Floyd-Warshall 最短路算法,它可以方便的求得任意两点 ...

  7. C#基础知识---?为何物

    一. 可空类型修饰符(?)引用类型可以使用空引用表示一个不存在的值,而值类型通常不能表示为空.例如:string str=null; 是正确的,int i=null; 编译器就会报错.可空类型的出现, ...

  8. jsoup的Document类

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

  9. mfc HackerTools全局钩子

    钩子英文名叫Hook,是一种截获windows系统中某应用程序或者所有进程的消息的一种技术. 如在键盘中按下一键,操作系统将收到键按下消息,把消息放入消息队列,然后消息队列对消息进行派发,发给相应的应 ...

  10. 等待唤醒机制----线程池----lambda表达式

    1.等待唤醒机制 1.1线程间通信 概念:多个线程在处理同一个资源,但是处理的动作(线程的任务)却不相同. 比如:线程A用来生成包子的,线程B用来吃包子的,包子可以理解为同一资源,线程A与线程B处理的 ...