文档章节

php实现文件内容对比并加亮显示工具类

刘德生
 刘德生
发布于 2016/07/11 19:42
字数 751
阅读 47
收藏 3
点赞 0
评论 1

<?php
/**
* @desc  php实现文件对比工具类
*
* @author  刘德生
* @site  http://liudsh.duapp.com/
* @since 2016-07-11
*/

class fileDiff {
    /**
     * 获取文件
     *
     * @param array $arrParam
     * @return array
     */
    public function diff($strContent1, $strContent2) {
        //按行拆分文件
        $arrContentLine1 = explode(PHP_EOL, $strContent1);
        $arrContentLine2 = explode(PHP_EOL, $strContent2);
        $intN1 = count($arrContentLine1);
        $intN2 = count($arrContentLine2);
        $strAjustLine = '<span style="background:#0b0;">&nbsp;&nbsp;</span><br/>';
        if (!$strContent1) {
            $strRet2 = $this->_setDiffColor($strContent2);
            $strRet2 = str_replace(PHP_EOL, '<br/>', $strRet2);
            $strRet1 = str_repeat($strAjustLine, $intN2);
        } else if (!$strContent2) {
            $strRet1 = $this->_setDiffColor($strContent1);
            $strRet1 = str_replace(PHP_EOL, '<br/>', $strRet1);
            $strRet2 = str_repeat($strAjustLine, $intN1);
        } else {
            $strRet1 = $strRet2 = ''; //对比结果    
            for($i=0,$j=0; $i < $intN1 && $j < $intN2; ++$i,++$j) {
                if (empty($arrContentLine1[$i]) && $arrContentLine2[$j]) {
                    $strRet1 .= '<br/>';
                    $strRet2 .= $strAjustLine;
                    --$j;
                    continue;
                }
                if (empty($arrContentLine2[$j]) && $arrContentLine1[$i]) {
                    $strRet1 .= $strAjustLine;
                    $strRet2 .= '<br/>';
                    --$i;
                    continue;
                }
                
                $arrCmp = $this->_diffLine($arrContentLine1[$i], $arrContentLine2[$j]);
                if ($arrCmp['is_same'] != 1) {//不相同
                    //剩余行数
                    $intL1 = $intN1 - $i - 1; 
                    $intL2 = $intN2 - $j - 1;
                    if ($intL1 > $intL2) {
                        $intDiff = $intL1 - $intL2;
                        $intSkip = 0; //大于0表示数组1迁移几行有相同
                        $arrDiffTmp = array();
                        $strSameTmp = '';
                        for($k=1; $k<=$intDiff; ++$k) {
                            $arrTmp = $this->_diffLine($arrContentLine1[$i+$k], $arrContentLine2[$j]);
                            if ($arrTmp['is_same'] == 1) { //相同
                                $intSkip = $k;
                                $strSameTmp = $arrContentLine2[$j];
                                break;
                            } else {
                                $arrDiffTmp[] = $arrContentLine1[$i+$k];
                            }
                        }
                        if ($intSkip > 0 || $intL2 == 0) {
                            $strRet1 .= $this->_setDiffColor($arrContentLine1[$i]) . '<br/>'; 
                            $strRet2 .= $strAjustLine;
                            $i += $intSkip;
                            if ($arrDiffTmp) {
                                foreach ($arrDiffTmp as $str) {
                                    $strRet1 .= $this->_setDiffColor($str). '<br/>';
                                    $strRet2 .= $strAjustLine;
                                }
                            }
                            $strRet1 .= $strSameTmp. '<br/>';
                            $strRet2 .= $strSameTmp. '<br/>';
                        } else {
                            $strRet1 .= $arrCmp['str1'] . '<br/>';
                            $strRet2 .= $arrCmp['str2'] . '<br/>'; 
                        }
                    } else if ($intL1 < $intL2) {
                        $intDiff = $intL2 - $intL1;
                        $intSkip = 0; //大于0表示数组1迁移几行有相同
                        $arrDiffTmp = array();
                        $strSameTmp = '';
                        for($k=1; $k<=$intDiff; ++$k) {
                            $arrTmp = $this->_diffLine($arrContentLine1[$i], $arrContentLine2[$j+$k]);
                            if ($arrTmp['is_same'] == 1) { //相同
                                $intSkip = $k;
                                $strSameTmp = $arrContentLine1[$i];
                                break;
                            } else {
                                $arrDiffTmp[] = $arrContentLine2[$j+$k];
                            }
                        }
                        
                        if ($intSkip > 0 || $intL1 == 0) {
                            $strRet1 .= $strAjustLine;
                            $strRet2 .= $this->_setDiffColor($arrContentLine2[$j]) . '<br/>'; 
                            $j += $intSkip;
                            if ($arrDiffTmp) {
                                foreach ($arrDiffTmp as $str) {
                                    $strRet1 .= $strAjustLine;
                                    $strRet2 .= $this->_setDiffColor($str). '<br/>';
                                }
                            }
                            $strRet1 .= $strSameTmp. '<br/>';
                            $strRet2 .= $strSameTmp. '<br/>';
                        } else {
                            $strRet1 .= $arrCmp['str1'] . '<br/>';
                            $strRet2 .= $arrCmp['str2'] . '<br/>'; 
                        }
                    } else {
                        $strRet1 .= $arrCmp['str1'] . '<br/>';
                        $strRet2 .= $arrCmp['str2'] . '<br/>';
                    }
                } else {
                    $strRet1 .= $arrCmp['str1'] . '<br/>';
                    $strRet2 .= $arrCmp['str2'] . '<br/>';
                }
            }
        }
        
        $arrRet = array(
            'content1' => $strRet1,
            'content2' => $strRet2,
        );
        
        return $arrRet;
    }
    
    /**
     * 按行对比
     *
     * @param string $str1
     * @param string $str2
     * @return array
     */
    private function _diffLine($str1, $str2) {
        $strSplit = "/[\s,.!?:;。,!?;]+/u";
        $arrWord1 = preg_split($strSplit, $str1, -1, PREG_SPLIT_OFFSET_CAPTURE);
        $arrWord2 = preg_split($strSplit, $str2, -1, PREG_SPLIT_OFFSET_CAPTURE);
        $intN1 = count($arrWord1);
        $intN2 = count($arrWord2);
        $arrFlag1 = $arrFlag2 = array();//标记相同部分
        for($i=0,$j=0; $i < $intN1 && $j < $intN2; ++$i,++$j) {
            if ($arrWord1[$i][0] != $arrWord2[$j][0]) {
                //剩余部分份数
                $intL1 = $intN1 - $i - 1; 
                $intL2 = $intN2 - $j - 1;
                if ($intL1 > $intL2) {
                    $intDiff = $intL1 - $intL2;
                    $intSkip = 0; //大于0表示数组1迁移几位有相同
                    for($k=1; $k<=$intDiff; ++$k) {
                        if ($arrWord1[$i+$k][0] == $arrWord2[$j][0]) { //相同
                            $intSkip = $k;
                            break;
                        }
                    }
                    if ($intSkip > 0) {
                        $i += $intSkip;
                        $arrFlag1[$i] = 1;
                        $arrFlag2[$j] = 1;
                    } 
                } else if ($intL1 < $intL2) {
                    $intDiff = $intL2 - $intL1;
                    $intSkip = 0; //大于0表示数组1迁移几位有相同
                    for($k=1; $k<=$intDiff; ++$k) {
                        if ($arrWord2[$j+$k][0] == $arrWord1[$i][0]) { //相同
                            $intSkip = $k;
                            break;
                        }
                    }
                    if ($intSkip > 0) {
                        $j += $intSkip;
                        $arrFlag1[$i] = 1;
                        $arrFlag2[$j] = 1;
                    } 
                } 
            }else {
                $arrFlag1[$i] = 1;
                $arrFlag2[$j] = 1;
            }
        }
        
        $strRet = '';
        $pos = 0;
        for($k=0; $k < $intN1; ++$k) {
            if ($k > 0) {
                $strRet .= substr($str1, $pos, $arrWord1[$k][1]-$pos);
            } 
            if ($arrFlag1[$k]) {
                $strRet .= $arrWord1[$k][0];
            } else {
                $strRet .= $this->_setDiffColor($arrWord1[$k][0]);
            }
            $pos = $arrWord1[$k][1] + strlen($arrWord1[$k][0]);
        }
        $arrRet = array();
        $arrRet['str1'] = $strRet;
        $strRet = '';
        $pos = 0;
        for($k=0; $k < $intN2; ++$k) {
            if ($k > 0) {
                $strRet .= substr($str2, $pos, $arrWord2[$k][1]-$pos);
            }
            if ($arrFlag2[$k]) {
                $strRet .= $arrWord2[$k][0];
            } else {
                $strRet .= $this->_setDiffColor($arrWord2[$k][0]);
            }
            $pos = $arrWord2[$k][1] + strlen($arrWord2[$k][0]);
        }
        $arrRet['str2'] = $strRet;
        $arrRet['is_same'] = ($intN1 == $intN2 && count($arrFlag1) == $intN1 && count($arrFlag2) == $intN2)?1:0;
        return $arrRet;
    }
    
    /**
     * 设置不同文字颜色
     *
     * @param string $str
     * @return string
     */
    private function _setDiffColor($str) {
        return '<span style="color:#ff5809">' . $str . '</span>';
    }
}

© 著作权归作者所有

共有 人打赏支持
刘德生
粉丝 6
博文 31
码字总数 7734
作品 0
海淀
高级程序员
加载中

评论(1)

PHP语法加亮类--KindSyntax

KindSyntax是用PHP做的程序语法加亮类,支持HTML、 JavaScript、 PHP、 Perl等语言的高亮显示,可以替代PHP自带的highlight函数。 使用方法请参考压缩包里的README.txt文件。 在线演示:htt...

匿名 ⋅ 2008/11/30 ⋅ 0

C/C++集成开发环境--C-Free

C-Free是一款支持多种编译器的专业化C/C++集成开发环境(IDE)。利用本软件,使用者可以轻松地编辑、编译、连接、运行、调试C/C++程序。 C-Free 5 主要有以下特性: 1. 支持多编译器,可以配...

匿名 ⋅ 2012/09/19 ⋅ 0

Spuria - 一个用C#写的让图片边缘颜色变浅的工具

一、Spuria编写目的 昨天晚上因为需要把一些照片的边缘变亮(或者说变浅),突然有了写一个程序去处理的想法。Spuria可以读取一张图片,将图片的边缘部分加亮,然后将处理后的图片保存到用户...

北风其凉 ⋅ 2014/09/11 ⋅ 0

C-Free汉化版

名称:C-Free汉化版版本:1.0软件大小:14.1MB软件语言:简体中文软件授权:免费版应用平台:Win7/Vista/Win2003/WinXPC-Free是一款支持多种编译器的专业化C/C++集成开发环境(IDE)。利用C...

相心的泪 ⋅ 2016/08/01 ⋅ 0

PHP代码加亮工具——GeSHi 的安装和使用

代码加亮工具GeSHi的安装轻而易举,即便对PHP新手也一样,不需要什么技巧^_^ GeSHi需要如下环境: PHP 4.1.0以上 作者在 4.3.X 环境下进行了测试。同时,大量的应用表明GeSHi的稳定性很好,适...

红薯 ⋅ 2010/09/16 ⋅ 3

FineReader如何不通过识别快速创建电子档案

很多用户每天都要处理大量传入的文档,比如,律师要处理案例和客户的成千上万个文档页面,这些案例文档经常几乎同时出现,要么就是接踵而至,文档附件需快速制作,工作才能得以开始。怎样才能...

ABBYY ⋅ 2015/12/09 ⋅ 0

PHP 开发环境配置

                 使用phpStudy +Zend Studio 使用phpStudy +Zend Studio ,这个组合是我个人使用的比较好的,现在分享出来。 一、phpStudy简体中文版 该程序包集成最新的A...

zting科技 ⋅ 2017/11/01 ⋅ 0

ls 命令总结

ls—list directory contents(显示目录内容) 【语法】:ls【选项】【参数】 【功能介绍】 ls指令用来显示目录列表,在Linux系统中有着较高的使用率。ls指令的输出信息可以进行颜色加亮显示...

luoahong ⋅ 2016/12/02 ⋅ 0

RTemplate,使用PHP5进行模板开发

关于PHP下的其他模板程序我就不多做介绍,我们只谈一谈今天的主角:RTemplate。 RTemplate 是 phpguru.org 下的一个开源项目,使用PHP5开发、并进行模板设计,免去了再去学习一门语言的麻烦。...

Byggvir ⋅ 2010/01/26 ⋅ 0

File Thingie文件管理小之灵

开源项目中文件管理工具的确很多,基本功能都是实现文件的上传、下载、编辑、删除。 File Thingie是一个由PHP编写的基于Web的文件管理工具,它的好处就在于体型小,功能全。 整个软件就由一个...

junwong ⋅ 2012/03/09 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

JAVA RMI

什么是JAVA RMI Java RMI (Remote Method Invocation) 远程方法调用,能够让客户端像使用本地调用一样调用服务端 Java 虚拟机中的对象方法。RMI 是面向对象语言领域对 RPC (Remote Proced...

saulc ⋅ 32分钟前 ⋅ 0

Linux系统工程狮养成记

如今的社会,随着时代的发展,出现了很多职业,像电子类,计算机类的专业,出现了各种各样的工程师,有算法工程师,java工程师,前端工程师,后台工程师,Linux工程师,运维工程师等等,不同...

linux-tao ⋅ 42分钟前 ⋅ 0

进入编辑模式 vim命令模式 vim实践

1.

oschina130111 ⋅ 42分钟前 ⋅ 0

mysql用户管理、常用sql语句、mysql数据库备份恢复

1. mysql用户管理 mysql默认有一个root超级管理员账户,实际工作环境中不可能每个人都用此root权限,防止误操作、误删除,可以给单独的用户进行授权。 Mysql创建用户以及授权: grant all on...

laoba ⋅ 43分钟前 ⋅ 0

类型后面三个点(String...)和数组(String[])的区别

类型后面三个点(String…),是从Java 5开始,Java语言对方法参数支持一种新写法,叫可变长度参数列表,其语法就是类型后跟…,表示此处接受的参数为0到多个Object类型的对象,或者是一个Obj...

流氓兔- ⋅ 49分钟前 ⋅ 0

JEPLUS表格组件之表格合并——JEPLUS软件快速开发平台

JEPLUS表格组件之表格合并 我们在列表配置时会遇见这样的一种情况,需要对个人的数据进行统一化,对一些数据进行归类,这样展示出来美观又直观,在这篇笔记中我来给大家介绍下如何配置出来专...

JEPLUS ⋅ 50分钟前 ⋅ 0

golang 并发中全局唯一操作

package main// go 携程共享 数据// 加锁解锁操作// 同步锁import ("sync""fmt")// 创建Once结构var once = sync.Once{}func computed(data *int, lock *sync.Mut...

304158 ⋅ 50分钟前 ⋅ 0

Mobx入门之二:asynchronous actions

这一节主要看mobx怎么实现asynchronous actions 1 要实现的demo功能 输入地名,查询天气,利用openweathermap api 2 思想 observable观察数据:location地点、temperature温度 observer响应式...

pengqinmm ⋅ 53分钟前 ⋅ 0

【2018.0620学习笔记】【linux高级知识 13.4-13.6】

13.4 mysql用户管理 创建用户并授权: grant all on *.* to '用户名'@'ip' identified by '密码' //all是操作权限,*.*是库.表,指定格式是'用户名'@'localhost'才能用socket登录本地 gra...

lgsxp ⋅ 今天 ⋅ 0

Java强弱引用示例

package jdk;import java.lang.ref.PhantomReference;import java.lang.ref.ReferenceQueue;import java.lang.ref.SoftReference;import java.lang.ref.WeakReference;public ......

月下狼 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部