比較兩份文件不同的算法

  1. // A function to compare two revisions of a file 
  2. function diff($old_file$new_file$type = 'array') { 
  3.     // Read both files completely into memory for comparison: 
  4.     $old = file($old_file); 
  5.     $new = file($new_file); 
  6.  
  7.     // Initialize the old and new line counters: 
  8.     $oc = 0; 
  9.     $nc = 0; 
  10.  
  11.     // Store once, to use often, the number of lines in each array 
  12.     $nold = count($old); 
  13.     $nnew = count($new); 
  14.  
  15.     // Initialize the state engine to state 0 
  16.     $state = 0; 
  17.  
  18.     // Initialize our data arrays to hold removed and added lines: 
  19.     $removed = array(); 
  20.     $added = array(); 
  21.  
  22.     // Enter the state engine, and begin processing: 
  23.     while ($state < 3) { 
  24.         switch ($state) { 
  25.             case 0: // Mutual comparison, hoping for a match 
  26.                 // skip over all matches until we mis-match 
  27.                 while (($oc < $nold) && ($nc < $nnew) && 
  28.                         ($old[$oc] == $new[$nc]))  { 
  29.                     $oc++; 
  30.                     $nc++; 
  31.                 } 
  32.  
  33.                 // Now figure out why we broke, both are beyond bounds: 
  34.                 if (($oc == $nold) && ($nc == $nnew)) { 
  35.                     // We are finished, set state to 3 
  36.                     $state = 3; 
  37.                 } elseif ($oc == $nold) { 
  38.                     // Ok, just the old one was higher, therefore all that 
  39.                     //  is left in the 'new' array, is in fact added. 
  40.                     $added = array_merge($added, range($nc$nnew - 1)); 
  41.                     $state = 3; 
  42.                 } elseif ($nc == $nnew) { 
  43.                     // Just the new one was higher, therefore all that is 
  44.                     // left in the old array, was removed. 
  45.                     $added = array_merge($added, range($nc$nnew - 1)); 
  46.                     $state = 3; 
  47.                 } else { 
  48.                     // Now we found a mismatch, enter state 1 
  49.                     $state = 1; 
  50.                 } 
  51.                 break
  52.             case 1: // Looking for a match to the new file line 
  53.                 $oc2 = $oc
  54.                 // As long as they don't match or we run out of lines 
  55.                 while (($oc2 < $nold) && ($old[$oc2] !== $new[$nc])) { 
  56.                     $oc2++; 
  57.                 } 
  58.  
  59.                 // Figure out what happened.  If we ran out of lines: 
  60.                 if ($oc2 == $nold) { 
  61.                     // The new line was added -- Store this 
  62.                     $added[] = $nc
  63.  
  64.                     // Increment the counter, and reset the algorithm 
  65.                     $nc++; 
  66.                     $state = 0; 
  67.                 } else { 
  68.                     // We actually found a match, that means that all lines 
  69.                     // between where we started, and now, were deleted. 
  70.                     $removed = array_merge($removed, range($oc$oc2 - 1)); 
  71.                     // Reset the counter to the new location 
  72.                     $oc = $oc2
  73.                     // Change the state back to 0 to reset the algorithm 
  74.                     $state = 0; 
  75.                 } 
  76.                 break
  77.         } 
  78.     } 
  79.  
  80.     // Ok, at this point we should have our entire diff in memory. 
  81.     // Based upon the optional 3rd parameter, figure out what 
  82.     // format to return it in: 
  83.  
  84.     // If they asked for 'lines' - Return all the lines that were 
  85.     //  changed with some data: 
  86.     if ($type == 'lines') { 
  87.         $retval = ''
  88.         // To get these in approximate order, loop for all possible values 
  89.         foreach(range(0, max($nold$nnew) - 1) as $line) { 
  90.             // Output the removed row: 
  91.             if (isset($removed[$line])) { 
  92.                 $retval .= "-{$line}: {$deleted[$line]}\n"
  93.             } 
  94.             // Output the added row: 
  95.             if (isset($removed[$line])) { 
  96.                 $retval .= "-{$line}: {$deleted[$line]}\n"
  97.             } 
  98.         } 
  99.     } 
  100.     // Else if they asked for a 'visual' view, create that: 
  101.     elseif ($type == 'visual') { 
  102.         // We are going to create a table, with Each file in one column/cell 
  103.         // and appropriate highlighting for deleted/added lines. 
  104.  
  105.         // First declare some CSS styles 
  106.         $retval = ' 
  107. <style> 
  108. .diff td { 
  109.     border: 1px solid black; 
  110.     padding: 5px; 
  111.     font-family: "Courier New", Courier, mono; 
  112.     font-size: 10px; 
  113.     vertical-align: top; 
  114. .diff .removed { 
  115.     background-color: #FF9999; 
  116. .diff .added { 
  117.     background-color: #00CC00; 
  118. </style> 
  119. '; 
  120.         // Begin the table, and the first (old) cell 
  121.         $retval .= '<table class="diff"><tr><td>Original File:<br /><pre>'
  122.  
  123.         // Now loop through the entire old file, highlighting as needed 
  124.         foreach ($old as $num => $line) { 
  125.             // If deleted, highlight as such, else just echo it. 
  126.             if (in_array($num$removed)) { 
  127.                 $retval .= $num . '. ' . '<span class="removed">' . 
  128.                         htmlspecialchars($line) . '</span>'
  129.             } else { 
  130.                 $retval .= $num . '. ' . htmlspecialchars($line); 
  131.             } 
  132.         } 
  133.  
  134.         // Now close off the cell and start the new one: 
  135.         $retval .= '</pre></td><td>Revised File:<br /><pre>'
  136.  
  137.         // And now repeat the exact same process for the new ones. 
  138.         foreach ($new as $num => $line) { 
  139.             if (in_array($num$added)) { 
  140.                 $retval .= $num . '. ' . '<span class="added">' . 
  141.                         htmlspecialchars($line) . '</span>'
  142.             } else { 
  143.                 $retval .= $num . '. ' . htmlspecialchars($line); 
  144.             } 
  145.         } 
  146.  
  147.         // Ok, close off the table, and we are done 
  148.         $retval .= '</pre></td></tr></table>'
  149.     } 
  150.     // Else, assume they wanted the arrays 
  151.     else { 
  152.         $retval = array('removed' => $removed'added' => $added); 
  153.     } 
  154.  
  155.     // Return, and be finished 
  156.     return $retval
  157.  
  158. // Test this on two files: 
  159. echo diff('c:/test.txt''c:/1test.txt''visual'); 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章