尝试在javascript中实现一个简单的文本解析器

时间:2014-03-02 13:03:11

标签: javascript

我正在尝试将一个简单的文本解析器从Java带到Javascript。

需要将给定的csv文件转换为另一种格式。原始文件根据某些行中的一个id列出了许多值:

例如:
11111; 12; 23; 23; ....
11111; 32; 12; 12; ....

因此,第一个值是Id,其他值是根据此Id。 现在我需要相同的文件,在一行中根据一个Id的值。 结果应该是这样的:
11111; 12; 23; 23; 32; 12; 12; ....

我已经通过一个简单的Java类实现了这个目标:

public static void main(String[] args) throws Exception {
        PrintWriter writer = new PrintWriter("t2_lines.csv", "UTF-8");
        BufferedReader br = new BufferedReader(new FileReader("t2.csv"));

        String previousId="";
        String line;

        while ((line = br.readLine()) != null) {
            String [] words = line.split(";");
            String id = words[0];
            if (previousId.equals(id)){
                // the loop starts at 4 to cut out some unneded values
                for(int i=4;i<words.length;i++) {
                    writer.print(words[i]+";");
                }
            }else{
                writer.println("");
                for(String word : words)
                writer.print(word+";");
                previousId = id;
            }
    }
        br.close();
        writer.close();
    }

现在我尝试通过从客户端读取文件并在文本字段中显示结果来重建Javascript中的这个东西 - 但遗憾的是我之前从未在Javascript中实现任何内容...

到目前为止,这是我的方法:

window.onload = function () {
var fileInput = document.getElementById('fileInput');
var origFileDisplayArea = document.getElementById('origFileDisplayArea');
var reformatFileDisplayArea= document.getElementById('reformatFileDisplayArea');

fileInput.addEventListener('change', function (e) {
    var file = fileInput.files[0];
    var textType = /text.*/;

    if (file.type.match(textType)) {
        var reader = new FileReader();

        reader.readAsText(file);

        reader.onload = function (e) {
            var result = reader.result;
            var table = parse(result);
            origFileDisplayArea.innerText = table;
        }
    } else {
        origFileDisplayArea.innerText = "File not supported!"
    }
});
}

function parse(input) {
var previousId = "";
var table = "";
if (typeof input !== "undefined")
var lines = input.split("\n");
for (var i = 0; i <= lines.length; i++) {
    var line = lines[i];
    if (typeof line !== "undefined")
    var words = line.split(";");
    console.log("words length: ", words.length);
    for (var j = 0; j <= words.length; j++ ) {
        var word = words[j];

        if (typeof word !== "undefined") {
            word.toString();
            var id = words[0];
            if (previousId === id) {
                for (var jj = 4; jj <=words.length; jj++){
                    console.log("jj: " + jj)
                    table += words[jj]+";";
                }
            }else {
                table += "\n";
                for (var word in words) {
                    table += word + ";";
                    previousId = id;
                }
            }
        }
    }


}

return table;
}

但不幸的是,我现在因为未定义的值而陷入困境,整个事情需要花费很长时间才能运行。

因此,非常感谢任何提示/帮助。 提前致谢

1 个答案:

答案 0 :(得分:0)

对于 FileReader 是的,我无法在这种情况下看到避免这种情况的方法。这看起来不像你遇到问题的地方。

对于parsesplit方法会占用大量内存,因此我会避免在整个文件中使用它,而for..in并非设计用于循环阵列

function parse(str_in) {
    var i = -1, j = -1,
        str_out = '',
        last_id = '',
        words;
    str_in += '\n'; // not sure if necessary - let the last line pass `while`
    // loop by seeking out the next new line
    // i = old_index + 1
    // j = next \n after old_index
    // .slice(i, j) gives just the line
    while (-1 !== (j = str_in.indexOf('\n', i = j + 1))) {
        words = str_in.slice(i, j).split(';')
        // loop words to trim whitespace here if you want
        if (last_id === words[0]) // throw away first item if on the same id
            words = words.slice(1);
        else {
            last_id = words[0];
            if (str_out.length) // lazy prevent first char newline
                str_out += '\n';
        }
        str_out += words.join(';'); // if you trimmed witespace, re-add here
        // if you don't have a final semicolon, add it too
    }
    return str_out;
}

现在

parse('11111; 12; 23; 23 ;\n11111; 32; 12; 12 ;');
// "11111; 12; 23; 23 ; 32; 12; 12 ;"

或者,您可能会发现编写与 Java 中使用的方法类似的方法更容易,因此您可以使用最少的更改,例如。

function ReadLineGenerator(text) {
    var start = -1, end = -1;
    return function readLine() {
        if (end < start) {
            start = end = -1;
            return null;
        }
        start = end + 1;
        end = text.indexOf('\n', start);
        if (end !== -1)
            return text.slice(start, end);
        else
            return text.slice(start);
    };
}
// example usage
var str = 'a\nb\nc',
    f = ReadLineGenerator(str),
    line;
while (null !== (line = f()))
    console.log(line);
// "a", "b", "c" logged
// line === null