解析未知格式的文件时检索列边界是个好主意吗?

问题描述 投票:0回答:1

想象我们有一些扩展名为*。unknown的文件,需要对其进行解析。

不幸的是,我们不知道如何准确地解析它……没有超级解析器或简单的“由空格逻辑分割”。

这里最好的方法是从透视角度出发:创建一个特殊的功能来帮助您以更通用的方式检索数据,或者只是不要过分考虑问题和列边界的硬编码限制,希望文件内容不会在不久的将来发生巨大变化吗?

具体来说,这是数据:

Name            Address               Postcode Phone          Sum     
AA, BB          Somethin 34           123123   020 123        1000000
CC, DD          kwnqdklnqwe 96        87823    +44 728 889838 989830

长期最佳方法是什么?

predetermined hard-coded column borders = [0, 16] [16, 38] [38, 47] [47, 61] [61, 74]

VS

// dynamic column borders determination

String[] headerNames = {"Name", "Address", "Postcode", "Phone", "Sum"};
List<int[]> borders = new ArrayList<>();

private void determineColumnBorders(String[] headerNames, String headerLine, List<int[]> borders) {
    int previous = 0, next;
    for (int i = 0; i < headerNames.length; i++) {
        next = i + 1 == headerNames.length ? headerLine.length() : headerLine.indexOf(headerNames[i + 1]);
        borders.add(new int[]{previous, next});
        previous = next;
    }
}

//And then, during the parsing, you can call it like borders.get(0)[0], borders.get(0)[1]...
algorithm text-parsing
1个回答
0
投票

如果您愿意对至少某些文件进行第一次传递,我可以看到两种解决方法:

  1. 为每行保留一个非空格字符的掩码,然后查找所有行共有的空格。这些延伸的末端就是字段的末端。
  2. 寻找两个或多个空格的延伸,并在每一行标记其结尾。如果这些位置的任何地方都没有非空格字符,则这些拉伸的末端为字段末端。

这两种方法都是试探法,它们假定所有字段都在左边对齐并且格式在整个文件中都是一致的。

这是在C中寻找所有行中公共空间的方式。(请注意,这会将示例中地址中的96识别为单独的字段。]

char mask[LINE_MAX] = {0};      // mask of non-space characters
char line[LINE_MAX];
size_t maxlen = 0;

while (fgets(line, sizeof(line), f)) {
    size_t n = 0;

    for (; line[n] && line[n] != '\n'; n++) {
        if (line[n] != ' ') mask[n] = 1;
    }

    if (n > maxlen) maxlen = n;
}

size_t i = 0;

while (i < maxlen && mask[i] == 0) i++;

while (i < maxlen) {
    size_t start = i;

    while (i < maxlen && mask[i]) i++;
    while (i < maxlen && mask[i] == 0) i++;
    printf("[%zu, %zu] ", start, i);
}

puts("");

这是第二种方法的C代码,该方法查找两个或多个空格的延伸:

char mask[LINE_MAX] = {0};      // has non-space somewhere
char span[LINE_MAX] = {0};      // is the end of a span of 2+ spaces
char line[LINE_MAX];
size_t maxlen = 0;

while (fgets(line, sizeof(line), f)) {
    size_t n = 0;

    while (line[n] == ' ') n++;

    while (line[n]) {
        if (line[n] == ' ' && line[n + 1] == ' ') {
            while (line[n] == ' ') n++;
            span[n - 1] = 1;
        }

        if (line[n] != ' ') mask[n] = 1;

        n++;
    }

    if (n > maxlen) maxlen = n;
}

size_t last = 0;
for (size_t i = 0; i < maxlen; i++) {
    if (span[i] && mask[i] == 0) {
        printf("[%zu, %zu] ", last, i + 1);
        last = i + 1;
    }
}

printf("[%zu, %zu]\n", last, maxlen);

两个示例都只是打印出他们找到的字段,因为我很懒。

您还可以使用这些策略通过在文件中查找一致的空格来测试某些硬编码的字段大小是否与数据匹配。

© www.soinside.com 2019 - 2024. All rights reserved.