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

时间:2013-08-29 18:49:03

标签: javascript

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

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

我尝试在iframe中打开这些文件(我让它看不见),但是一旦打开文件,我似乎无法访问这些文件的内容。我意识到有相同的原则规则,但我会从html文件所在的同一个驱动器中读取文件,我认为这应该是合法的(?)。我不确定我的问题是否与我对DOM的理解有关,或者这是不可能的。我对Javascript的了解很少/过时可能是真正的问题,但这似乎是一个奇怪的用例,所以我找不到任何例子。如果有浏览器的怪癖,我确实能够强制使用哪种浏览器。这是我到目前为止所做的,它只是一个测试,看看我已经加载了什么以及我正在访问什么。在Chrome中我没有添加任何内容,在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,这不值得吗?提前谢谢!

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

2 个答案:

答案 0 :(得分:0)

尝试在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";

答案 1 :(得分:0)

我更多地研究了这个。如果您想要访问本地文件而不需要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 - 允许文件访问文件

不知道firefox。

因此,在加载另一组文件之前必须(重新加载页面)的注意事项对我来说非常有效,所有文件都通过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>