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

<?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>';
    }
}

转载于:https://my.oschina.net/u/196016/blog/710023

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值