文档章节

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

刘德生
 刘德生
发布于 2016/07/11 19:42
字数 751
阅读 49
收藏 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)

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
PHP语法加亮类--KindSyntax

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

匿名
2008/11/30
1K
0
FineReader如何不通过识别快速创建电子档案

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

ABBYY
2015/12/09
24
0

没有更多内容

加载失败,请刷新页面

加载更多

转:XMLHttpRequest2 新技巧

”XMLHttpRequest 的异步调用网上找的例子运行没问题,但稍微改了一点点就报错”InvalidStateError: XMLHttpRequest has an invalid context“。断断续续 搞了3天终于通了,可以接收二进制文...

SamXIAO
19分钟前
0
0
=====D服务器定时任务=====

Linux定时任务 crontab linux系统是有cron这个系统服务来控制的,Liunx系统上包含很多的计划性工作,使用者自己可以设置计划任务,所以linux系统提供了使用者控制计划任务的命令 crontab的启...

覃光林
28分钟前
0
0
xilinx资源

本系列教学视频由赛灵思高级战略应用工程师带领你:从零开始,一步步深入 掌握 HLS 以及 UltraFAST 设计方法,帮助您成为系统设计和算法加速的大拿! http://www.eetrend.com/topics/2018-0...

whoisliang
39分钟前
2
0
企业级开源四层负载均衡解决方案--LVS

网盘链接 企业级开源四层负载均衡解决方案--LVS 本课程将在Linux环境下,学习配置使用LVS,对Web集群和MySQL集群进行负载均衡,并结合利用Keepalived实现负载均衡器的高可用,实现对后端Rea...

qq__2304636824
48分钟前
3
0
Windows上安装Spacemacs

emacs安装 下载地址emacs 安装比较简单,解压后执行\bin\addpm.exe即可 emacs配置 emacs的默认配置文件路径和.emacs.d文件夹都是在Windows主目录下的 C:\Users\Administrator\AppData\Roami...

yxmsw2007
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部