文档章节

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

刘德生
 刘德生
发布于 2016/07/11 19:42
字数 751
阅读 59
收藏 3

<?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
1K
0
C/C++集成开发环境--C-Free

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

匿名
2012/09/19
11.5K
0
C-Free汉化版

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

相心的泪
2016/08/01
56
0
Spuria - 一个用C#写的让图片边缘颜色变浅的工具

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

北风其凉
2014/09/11
0
0
FineReader如何不通过识别快速创建电子档案

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

ABBYY
2015/12/09
24
0

没有更多内容

加载失败,请刷新页面

加载更多

Windows 上安装 Scala

在安装 Scala 之前需要先安装 Java 环境,具体安装的详细方法就不在这里描述了。 您可以自行搜索我们网站中的内容获得其他网站的帮助来获得如何安装 Java 环境的方法。 接下来,我们可以从 ...

honeymose
今天
1
0
数据库篇多表操作

第1章 多表操作 实际开发中,一个项目通常需要很多张表才能完成。例如:一个商城项目就需要分类表(category)、商品表(products)、订单表(orders)等多张表。且这些表的数据之间存在一定的关系...

stars永恒
今天
3
0
nginx日志自动切割

1.日志配置(Nginx 日志) access.log----记录哪些用户,哪些页面以及用户浏览器,IP等访问信息;error.log------记录服务器错误的日志 #配置日志存储路径:location / {      a...

em_aaron
昨天
5
0
java 反射

基本概念 RTTI,即Run-Time Type Identification,运行时类型识别。RTTI能在运行时就能够自动识别每个编译时已知的类型。   要想理解反射的原理,首先要了解什么是类型信息。Java让我们在运...

细节探索者
昨天
2
0
推荐转载连接

https://www.cnblogs.com/ysocean/p/7409779.html#_label0

小橙子的曼曼
昨天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部