繁体   English   中英

解析大型CSV文件时,jQuery崩溃

[英]Jquery crashes while parsing large csv file

我有这个jquery函数,我在一个教程网站上发现了该函数,它接受一个csv文件输入并将其制成表格。 我尝试输入一个较大的csv文件(10,000KB),但我的浏览器崩溃了。 我看到有一个名为papa的解析器库来处理此问题,但是还有其他方法可以防止浏览器在执行此操作时崩溃吗?

以下是相关代码:

 $("#upload").bind("click", function () {

        var regex = /^([a-zA-Z0-9\s_\\.\-:])+(.csv|.txt)$/;
        if (regex.test($("#fileUpload").val().toLowerCase())) {
                            var reader = new FileReader();
                reader.onload = function (e) {
                    var table = $("<table id='mytable' class='table table-striped table-bordered'/>");
                    var rows = e.target.result.split("\n");
                    text1=e.target.result;
                    var csvString = $.trim(text1);
                    var csvRows    = csvString.split(/\n/);
                    var csvHeaders = csvRows.shift().split(';');
                    var headerstr=String(csvHeaders);
                    var count = (headerstr.match(/,/g) || []).length+1;
                    for (var i = 0; i < rows.length; i++) {
                        var row = $("<tr />");
                        var cells = rows[i].split(",");
                        for (var j = 0; j < count; j++) {

                            if(cells[j]){
                            var cell = $("<td/>");

                            cell.html(cells[j]);
                            }
                            else{
                            var cell = $("<td class='info'/>");
                            cell.html("empty");}
                            row.append(cell);

                        }
                        table.append(row);

                    }


                    $("#dvCSV").html('');
                    $("#dvCSV").append(table);
                }

    });

如何在不使浏览器崩溃的情况下实现此功能? 提前致谢。

解决此问题有两个大问题:

1)CSV解析器。 爸爸解析很棒。 它具有对worker的支持,并且是流解析器-处理大型文件的唯一方法。

2)显示数据的方式。 仅输出表中的每一行将不起作用。 我两次崩溃了PC,试图提出一个可行的解决方案。 这样做的唯一方法以及基本上任何处理大文件的系统都使用的方法是使用虚拟化列表。 我最终使用了这个 这很简单,代码也很容易理解。

这是我的JS:

$("#fUpload").bind("change", function(evt) {
    var bigFile = evt.target.files[0];
    var rows = [];
    Papa.parse(bigFile, {
        delimiter: ",",
        newline: "\n",
        header: false,
        dynamicTyping: false,
        worker: false,
        chunk: function(results) {
            rows.concat(rows, results.data);
        },
        complete: function() {
            var list = new VirtualList({
              h: 300,
              itemHeight: 30,
              totalRows: rows.length,
              generatorFn: function(row) {
                  var el = document.createElement("div");
                  el.innerHTML = "<p>ITEM " + row + ' -> ' + rows[row].join(' - ') + "</p>";
                  return el;
              }
            });
            document.body.appendChild(list.container)
        }
    });
});

HTML包含以下输入: <input type="file" id="fUpload" />

我如何配置Papa:

  • delimiternewline :如果允许它尝试检测它们,它将失败或花费更长的时间;

  • worker :这将产生一个worker进程。 这会比较慢, 但是将使UI保持响应状态(UI线程将无法执行任何工作)。 您可能需要在生产中将其设置为true (由于浏览器跨域安全协议,这在JSFiddle上将不起作用!);

  • chunk :不是解析过的每一行都有一个回调,而是有一个更大的行集。 这样更快。

虚拟列表配置是默认配置。

你可以在这里运行它。

我测试了一个9.4 MB的CSV文件,其中每行重复包含1,Foo,100

这是相同的,但是使用表来输出数据,并向VirtualList的totalRows添加了-1以补偿实际长度。

我建议您使用console.log('...')来确定它的锁定/中断位置,也许在第一个变量(行,csvString)中是因为大小。 因此,您可以知道在哪里进行攻击。

如果不在before循环块中,那么我认为在这种情况下使用jquery过于昂贵,因此请尝试直接使用DOM方法(至少在循环内部):

$("#upload").bind("click", function () {
    var regex = /^([a-zA-Z0-9\s_\\.\-:])+(.csv|.txt)$/;
    if (regex.test($("#fileUpload").val().toLowerCase())) {
                        var reader = new FileReader();
            reader.onload = function (e) {
                var table = $("<table id='mytable' class='table table-striped table-bordered'/>");
                var rows = e.target.result.split("\n");
                text1=e.target.result;
                var csvString = $.trim(text1);
                var csvRows    = csvString.split(/\n/);
                var csvHeaders = csvRows.shift().split(';');
                var headerstr=String(csvHeaders);
                var count = (headerstr.match(/,/g) || []).length+1;
                for (var i = 0; i < rows.length; i++) {
                    var row = document.createElement("tr");
                    var cells = rows[i].split(",");
                    for (var j = 0; j < count; j++) {
                        var cell = document.createElement("td");
                        if(cells[j]){

                        cell.appendChild(document.createTextNode(cells[j]));
                        }
                        else{
                            cell.setAttribute('class','info');
                            cell.appendChild(document.createTextNode("empty"));
                        }
                        row.appendChild(cell);

                    }
                    table.append(row);

                }


                $("#dvCSV").html('');
                $("#dvCSV").append(table);
            }

});

我没有测试此代码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM