javascript模擬git diff命令實現(xiàn)文本文件差異比較
更新時間:2023年12月05日 15:44:17 作者:狄龍疤
這篇文章主要為大家詳細介紹了javascript如何模擬git diff命令實現(xiàn)文本文件差異比較效果,文中的示例代碼講解詳細,感興趣的小伙伴可以參考下
diff.html:
<!DOCTYPE html> <html> <head> <title>文件比較</title> <meta charset="UTF-8"> </head> <body> <h1>文件比較</h1> <form> <label for="file1">版本1:</label> <input type="file" id="file1" name="file1"><br><br> <label for="file2">版本2:</label> <input type="file" id="file2" name="file2"><br><br> <button type="button" onclick="compare()">開始比較</button> </form> <div id = "div_info" style="width:1000px;height:500px;border:1px solid gray;overflow:auto"> </div> <script> var infoDiv = document.getElementById("div_info"); function compare() { var file1 = document.getElementById("file1").files[0]; var file2 = document.getElementById("file2").files[0]; var reader1 = new FileReader(); var reader2 = new FileReader(); reader1.readAsText(file1); reader2.readAsText(file2); var lines_v1 = null; var lines_v2 = null; reader1.onload = function() { lines_v1 = reader1.result.split('\n'); // printArray( lines_v1 ); reader2.onload = function() { lines_v2 = reader2.result.split('\n'); // printArray( lines_v2 ); // 比較兩個文檔的區(qū)別 docDiff( lines_v1,lines_v2 ); } } } function printArray( array ){ var len = array.length; for (let i = 0; i < len; i++){ console.log( "[" + array[ i ] + "]" ); } } function docDiff( lines_v1,lines_v2 ){ var dp = calculateShortestEditDistance(lines_v1, lines_v2); var index1 = lines_v1.length - 1; var index2 = lines_v2.length - 1; console.log("一共需要" + dp[ index1 ][ index2 ] + "步編輯操作"); var results = []; while ( index1 >= 0 && index2 >= 0 ){ var line_v1 = lines_v1[ index1 ]; var line_v2 = lines_v2[ index2 ]; if( line_v1 == line_v2 ){ // v1:...a // v2:...a // 原封不動的輸出 results.push( " " + line_v1 ); index1--; index2--; }else { // v1:...a // v2:...b // v1:... a // v2:... b // 此時,a修改修改為b var sed1 = 0; if( index1 > 0 && index2 >0 ){ sed1 = dp[index1 - 1][index2 - 1]; } // v1:...a // v2: ... b // 此時,需要插入b var sed2 = 0; if( index2 >0 ){ sed2 = dp[index1][index2 - 1]; } // v1: ... a // v2:...b // 此時,需要刪除a var sed3 = 0; if( index1 > 0 ){ sed3 = dp[index1-1][index2]; } var sed = Math.min( sed1,sed2,sed3 ); if( sed == sed1 ){ // results.add( "edit " + line_v2 + " DIFF:" + StringDiffTest.diff( line_v1,line_v2 ) ); // var diffInfo = StringDiffTest.diff(line_v1, line_v2); // results.add( "edit " + diffInfo ); results.push( "- " + line_v1 ); results.push( "+ " + line_v2 ); index1--; index2--; }else if( sed == sed2 ){ results.push( "+ " + line_v2 ); index2--; }else if( sed == sed3 ){ results.push( "- " + line_v1 ); index1--; } } } while ( index1 >= 0 ){ // v1 中多出的 "首行們" 都是需要刪除的 results.push( "- " + lines_v1[ index1 ] ); index1--; } while ( index2 >= 0 ){ // v2 中多出的 "首行們" 都是需要被插入的 results.push( "+ " + lines_v2[ index2 ] ); index2--; } for ( var i=results.length -1;i>=0;i-- ){ var line = results[ i ]; var small = document.createElement( "small" ); small.innerHTML = line; if( line.startsWith( "-" ) ){ small.style.color = "red"; }else if( line.startsWith( "+" ) ){ small.style.color = "green"; } infoDiv.appendChild( small ); infoDiv.appendChild( document.createElement( "br" ) ); } } // 返回 int[][] function calculateShortestEditDistance( lines_v1,lines_v2 ){ // dp[i][j] 表示的是將 lines_v1 的前i個元素變換為 lines_v2 中的前j個元素需要使用的最優(yōu)( 即需要轉(zhuǎn)換步驟最少 )的轉(zhuǎn)換方式 var size_v1 = lines_v1.length; var size_v2 = lines_v2.length; var dp = createArray( size_v1,size_v2 ); for (var index1 = 0; index1 < size_v1; index1++) { var line_v1 = lines_v1[ index1 ]; for (var index2 = 0; index2 < size_v2; index2++) { var line_v2 = lines_v2[ index2 ]; if( index1 == 0 ){ if( index2 == 0 ){ if( line_v1 == line_v2 ){ // v1:a // v2:a dp[ index1 ][ index2 ] = 0; }else { // v1:a // v2:b dp[ index1 ][ index2 ] = 1; } }else { if( contains( lines_v2,line_v1,0,index2 ) ){ // v1: a // v2:...a... size = index2 + 1 // v1轉(zhuǎn)換為 v2需要 size - 1步( 也就是 index2步 )插入操作 dp[ index1 ][ index2 ] = index2; }else { // v1: a // v2:...b... size = index2 + 1 // v1轉(zhuǎn)換為 v2需要 1步編輯操作,size-1= index2 步插入操作,一共index2 + 1步操作 dp[ index1 ][ index2 ] = index2 + 1; } } }else { if( index2 == 0 ){ if( contains(lines_v1, line_v2, 0, index1) ){ // v1:....a... size = index1 + 1 // v2: a // v1轉(zhuǎn)換為 v2需要 size-1=index1步刪除操作 dp[ index1 ][ index2 ] = index1; }else { // v1:....a... size = index1 + 1 // v2: b // v1轉(zhuǎn)換為 v2需要 1步編輯操作和size-1=index1步刪除操作,一共index1+1步操作 dp[ index1 ][ index2 ] = index1 + 1; } }else { if( line_v1 == line_v2 ){ // v1:...a // v2:...a dp[ index1 ][ index2 ] = dp[ index1 - 1 ][ index2 - 1 ]; }else { // v1:...a // v2:...b // v1:... a // v2:... b // 此時 v1 的前部分和 v2的前部分做dp運算,a修改為b var sed_prev1 = dp[ index1 - 1 ][ index2 - 1 ]; // v1: ... a // v2:...b // 此時v1的前部分和v2做dp運算,刪除a var sed_prev2 = dp[ index1 - 1 ][ index2 ]; // v1: ...a // v2: ... b // 此時 v1和v2的前部分做dp運算,插入b var sed_prev3 = dp[ index1 ][ index2 - 1 ]; dp[ index1 ][ index2 ] = Math.min( sed_prev1,sed_prev2,sed_prev3 ) + 1; } } } } } return dp; } // todo 測試行列是否寫反了 function createArray(rowCount, colCount) { var arr = []; for (var i = 0; i < rowCount; i++) { arr[i] = []; for (var j = 0; j < colCount; j++) { arr[i][j] = 0; } } return arr; } function contains(lines, targetLine, beginIndex, endIndex) { for (var i = beginIndex; i <=endIndex ; i++) { if( lines[ i ] == targetLine ){ return true; } } return false; } </script> </body> </html>
doc_v1.txt:
盼望著,盼望著,東風來了,春天的腳步近了。 一切都像剛睡醒的樣子,欣欣然張開了眼。 山朗潤起來了,水漲起來了,太陽的臉紅起來了。 小草偷偷地從土地里鉆出來,嫩嫩的,綠綠的。 園子里,田野里,瞧去,一大片一大片滿是的。 坐著,躺著,打兩個滾,踢幾腳球,賽幾趟跑,捉幾回迷藏。 風輕俏俏的,草軟綿綿的。 桃樹,杏樹,梨樹,你不讓我,我不讓你,都開滿了花趕趟兒。 紅的像火,粉的像霞,白的像雪。 花里帶著甜味;閉了眼,樹上仿佛已經(jīng)滿是桃兒,杏兒,梨兒。 花下成千成百的蜜蜂嗡嗡的鬧著,大小的蝴蝶飛來飛去。 野花遍地是:雜樣兒,有名字的,沒名字的,散在草叢里像眼睛像星星,還眨呀眨。 “吹面不寒楊柳風”,不錯的,像母親的手撫摸著你,風里帶著些心翻的泥土的氣息,混著青草味兒,還有各種花的香,都在微微潤濕的空氣里醞釀。 鳥兒將巢安在繁花嫩葉當中,高興起來,呼朋引伴的賣弄清脆的歌喉,唱出婉轉(zhuǎn)的曲子,跟清風流水應和著。 牛背上牧童的短笛,這時候也成天嘹亮的響著。 雨是最尋常的,一下就是三兩天。 可別惱??矗衽j?,像花針,像細絲,密密的斜織著,人家屋頂上全籠著一層薄煙。 樹葉卻綠得發(fā)亮,小草也青得逼你的眼。傍晚時候,上燈了,一點點黃暈的光,烘托出一片安靜而和平的夜。 在鄉(xiāng)下,小路上,石橋邊,有撐著傘慢慢走著的人,地里還有工作的農(nóng)民,披著所戴著笠。 他們的房屋稀稀疏疏的,在雨里靜默著。 天上的風箏漸漸多了,地上的孩子也多了。 城里鄉(xiāng)下,家家戶戶,老老小小,也趕趟似的,一個個都出來了。 舒活舒活筋骨,抖擻抖擻精神,各做各的一份事兒去。 “一年之計在于春”,剛起頭兒,有的是功夫,有的是希望 春天像剛落地的娃娃,從頭到腳都是新的,它生長著。 春天像小姑娘,花枝招展的笑著走著。 春天像健壯的青年,有鐵一般的胳膊和腰腳,領著我們向前去。
doc_v2.txt:
盼望著,盼望著,東風來了,春天的腳步進了。 一切都像剛睡醒的樣子,欣欣然張開了眼。 山朗潤起來了,水漲起來了,太陽的臉紅起來了。 小草偷偷地從土地里鉆出來,嫩嫩的,綠綠的。 園子里,田野里,瞧去,一大片一大片滿是的。 坐著,躺著,打兩個滾、踢幾腳球,賽幾趟跑、捉幾回迷藏。 風輕巧巧的,草軟綿綿的。 桃樹,杏樹,梨樹,你不讓我,我不讓你,都開滿了花趕趟兒。 紅的像火,粉的像霞,白的像雪。 花里帶著甜味;閉了眼,樹上仿佛已經(jīng)滿是桃兒,杏兒,梨兒。 花下成千成百的蜜蜂嗡嗡的鬧著,大小的蝴蝶非來非去。 野花遍地是:雜樣兒,有名字的,沒名字的,散在草叢里像眼睛像星星,還眨呀眨。 “吹面不寒楊柳風”,不錯的,像母親的手撫摸著你,風里帶著些心翻的泥土的氣息,混著青草味兒,還有各種花的香,都在微微潤濕的空氣里醞釀。 鳥兒將巢安在繁花嫩葉當中,高興起來,呼朋引伴的賣弄風騷清脆的歌喉,唱出婉轉(zhuǎn)的曲子,跟清風流水應和著。 牛背上牧童的斷敵,這時候也成天嘹亮的響著。 雨是最尋常的,一下就是三兩天。 可別惱。看,像牛牦,像花針,象細絲,密密的斜織著,人家屋頂上全籠著億層薄煙。 樹葉卻綠得發(fā)亮,小草也青得逼你的眼。傍晚時候,上燈了,一點點黃暈的光,烘托出一片安靜而和平的夜。 在鄉(xiāng)下,小路上,石橋邊,有撐著傘慢慢走著的人,地里還有工作的農(nóng)民,披星戴月著所戴著笠。 他們的房屋稀稀疏疏的,在雨里靜默著。 天上的風箏漸漸多了,地上的孩子也多了。 城里鄉(xiāng)下,家家戶戶,老老小小,也趕趟似的,一各各都出來了。 舒活舒活筋骨,抖擻抖擻精神,各做各的一份事兒去。 "一年之計在于春",剛起頭兒,有的是功夫,有的是希望 春天剛落地的娃娃,從頭到腳都是,它生長著。 春天像小菇娘,花枝招展的笑著走著。 春天像鍵壯的青年,有鐵一般的胳膊和腰腳,領著我們向前去。
測試效果:
以上就是javascript模擬git diff命令實現(xiàn)文本文件差異比較的詳細內(nèi)容,更多關(guān)于javascript文本比較的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
fiv.js實現(xiàn)flv文件blob流實時播放的項目實踐
本文主要介紹了fiv.js實現(xiàn)flv文件blob流實時播放的項目實踐,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-04-04JavaScript?中?this?關(guān)鍵字的作用及改變其上下文的方法
這篇文章主要介紹了JavaScript?中?this?關(guān)鍵字的作用和如何改變其上下文,通過使用?call,?apply,?bind?方法,可以改變函數(shù)中的?this?指向,從而在不同的上下文中使用同一個函數(shù),需要的朋友可以參考下2023-01-01javascript數(shù)組中的map方法和filter方法
這篇文章主要介紹了javascript數(shù)組中的map方法和filter方法,文章內(nèi)容介紹詳細,具有一定的參考價值,需要的小伙伴可以參考一下,希望對你的學習有所幫助2022-03-03For循環(huán)中分號隔開的3部分的執(zhí)行順序探討
這篇文章主要探討了For循環(huán)中分號隔開的3部分的執(zhí)行順序,需要的朋友可以參考下2014-05-05