想象我们有一些扩展名为*。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]...
如果您愿意对至少某些文件进行第一次传递,我可以看到两种解决方法:
这两种方法都是试探法,它们假定所有字段都在左边对齐并且格式在整个文件中都是一致的。
这是在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);
两个示例都只是打印出他们找到的字段,因为我很懒。
您还可以使用这些策略通过在文件中查找一致的空格来测试某些硬编码的字段大小是否与数据匹配。