使用Javascript在浏览器中创建文本文件diff

Creating text file diffs in the browser with Javascript

本文关键字:文本 文件 diff 创建 Javascript 浏览器 使用      更新时间:2023-09-26

我正在重写一个用于总结回归测试结果的脚本。正在测试的程序会吐出一些不同的文本文件,开发人员对这些文件在代码版本之间的任何更改都很感兴趣。旧的脚本在每个文件上使用命令行diff实用程序,这需要相当长的时间(有2000多个测试,每个测试要比较3个文件。在我们的标准开发机器上,这需要大约30分钟)。然后,它生成了一个HTML文件,其中包含一个表,该表具有指向所有非null diff的链接。

作为一名开发人员,我逐渐意识到,虽然它们通常很有用,但大多数diff从未被考虑过。为了加快这一过程,我的一个想法是使用Python filecmp.cmp工具比较文件,并创建一个包含所有差异的表。然后,使用diff_match_patch工具,使用Javascript仅区分单击的链接。这些结果将显示在浏览器中。我想我理解diff_match_patch的API,但我一直在尝试将这些文件加载到Javascript环境中。

我试过在iframe中打开这些文件(我会使其不可见),但一旦打开,我似乎就无法访问文件的内容。我意识到有相同的起源规则,但我会从html文件所在的同一驱动器读取文件,我认为这应该是合法的(?)。我不确定我的问题是我对DOM的理解,还是这根本不可能。我对Javascript的了解非常少/过时,这可能是真正的问题,但这似乎是一个奇怪的用例,所以我很难找到任何例子。如果浏览器有一个怪癖,我确实有能力强制使用哪种浏览器。这是我到目前为止所拥有的,这只是一个测试,看看我加载了什么以及我正在访问什么。在Chrome中,我没有在div中添加任何内容,而在Firefox中,我得到了"未定义":

<html>
<head>
  <script type="text/javascript" language="JavaScript">
    function changeSrc() {
    var base = document.getElementById("base");
    base.src="../result/test1.txt";
    var mod = document.getElementById("mod");
    mod.src="../result/test2.txt";
    var result =  mod.contentWindow.document.body.innerText;
    document.getElementById('result').innerHTML = '<BR>' + result;
    }
  </script>
</head>
<body>
  <iframe id="base" src=""></iframe>
  <iframe id="mod" src=""></iframe>
  <br>
  <span onClick="changeSrc();" style="cursor: pointer;">loadFiles</span>
  <br>
  <div id="result"></div>
</body>
</html>

如果有任何帮助,或者有人告诉我我在浪费时间,我将不胜感激。我也对其他开箱即用的想法持开放态度;考虑到我需要运行filecmp.cmp,也许节省的时间不值得这么麻烦?提前感谢!

编辑:我想这个问题分为两部分:1) 如何读取要在Javascript函数中使用的文本文件(作为字符串)?2) 这是个坏主意吗?

我对此进行了更多的研究。如果您想在不需要Web服务器的情况下访问本地文件,那么FileReader接口似乎更适合。

基本部分如下,但我的扩展实现(diff函数只是区分文件内容的长度)处理在异步加载输入文件后自动运行diff函数。

它还允许您将两个文件(作为两个文件中的一个选择)拖放到dropzone中。

这是我的公众jsFiddle SO18518842。

    var readFileUpdateUI = function(file, element, nameElement) {
        var reader = new FileReader();
        nameElement.innerText = "Loading...";
        reader.onerror = errorHandler;
        reader.onload = function(readEvent) {
            filesLoaded++;
            console.timeEnd('read of ' + file.name)
            var result = readEvent.target.result;
            //                console.log(result);
            element.innerText = result;
            nameElement.innerText = file.name;
            if (filesLoaded === 2) {
                diffFiles();
            }
        };
        console.time('read of ' + file.name)
        reader.readAsText(file);
    };

这个古老的答案因需要跑步而受阻chrome.exe--允许从文件访问文件

不知道萤火虫。

因此,这对我来说非常有效,但需要注意的是,在加载另一组文件之前必须(重新加载页面),所有文件都通过file://scheme访问,并且与此脚本位于同一目录中。

Firefox也需要重新加载。

Chrome和Firefox都会将所选文件的名称显示为(选择文件)按钮的工具提示。

除了text/plain(如accept属性中所定义)之外,Firefox还提供所有文件类型,而Chrome则不提供。

<html><head>
  <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
  <script type="text/javascript" language="JavaScript">
    function changeSrc() {
    var base = document.getElementById("base");
    var fileArray = document.getElementById('input').files
    base.src=fileArray[0].name;
    var mod = document.getElementById("mod");
    mod.src='./'+fileArray[1].name;
    var result =  mod.contentWindow.document.body.innerText;
    document.getElementById('result').innerHTML = '<BR>' + result;
    }
  </script>
</head>
<body>
  <iframe id="base" src=""></iframe>
  <iframe id="mod" src=""></iframe>
  <br>
  <div>
  <input type="file" accept="text/plain" id="input" multiple>
  </div>
  <div>
  <input type="button" onclick="changeSrc();" value="Load Files"/>
  </div>
  <div>
  <input type="button" onclick="location.reload(true);" value="Reload Page"/>
  </div>
  <br>
  <div id="result"></div>
</body></html>

尝试在onload处理程序中获取iframe的内容,而不是在设置了src之后立即获取。可能是您的获取代码正在启动,而浏览器仍在忙于加载iframe中的文件。

var mod = document.getElementById("mod");
mod.onload = function() {
    var result =  mod.contentWindow.document.body.innerText;
    document.getElementById('result').innerHTML = '<BR>' + result;
}
mod.src="../result/test2.txt";