读取文本文件时的Java分隔符 - 正则表达式/不是?

时间:2011-11-01 03:42:12

标签: java regex delimiter text-files separator

我正在尝试阅读以这种形式编写的文本文件:

    AB523:[joe, pierre][charlie][dogs,cat]
    ZZ883:[ronald, zigomarre][pele]

我想创建我的结构并正确检索信息。

AB523 ---单独
乔,皮埃尔---独自一人 查理---独自一人 狗,猫---独自一人

我不确定应该使用的最佳技术是什么。我已经尝试过StringTokenizer ...并使用regEx进行游戏,但我无法正确使用

你有解决方案吗?或建议

在文本文件中写入时的惯例是什么?分隔符的最佳实践是什么?

编辑:文本文件也由我生成,所以我可以控制整个模式。在重新阅读时减少工作量的最佳输出模式是什么?

5 个答案:

答案 0 :(得分:2)

我会在这里使用正则表达式,因为它似乎维护的代码较少,而且您的语言肯定是常规的。与java.util.Scanner实例一起提高效率。这是一些代码:

import java.io.Reader;
import java.io.StringReader;
import java.util.Scanner;
import java.util.regex.Pattern;

public class ScannerTest {

private static final Pattern header = Pattern.compile("(.*):");
private static final Pattern names = Pattern.compile("\\[([^\\]]+)\\]");

public static void main(String[] args) {

    Reader reader = new StringReader(
            "AB523:[joe, pierre][charlie][dogs,cat]\n"
                    + "ZZ883:[ronald, zigomarre][pele]");

    Scanner scanner = new Scanner(reader);
    scanner.useDelimiter("\n");

    while (scanner.hasNext()) {
        String h = scanner.findInLine(header);
        // Substring removes trailing ':'.
        System.out.println(h.substring(0, h.length() - 1));

        String n;
        while ((n = scanner.findInLine(names)) != null)
            // Substring removes '[' and ']'.
            System.out.println(n.substring(1, n.length() - 1));

        if (scanner.hasNext())
            scanner.nextLine();
    }
}
}

尽管如此,我仍然无法删除子字符串调用,也许这隐藏了一些低效率。我的猜测是,由于字符串的不变性,不应该为这种情况重新创建字符串。

编辑:为了获得更好的表现,我还会考虑手工制作的recursive descent parser

答案 1 :(得分:1)

使用String#splitPattern#split方法。 例如,

   String[] list ="AB523:[joe, pierre][charlie][dogs,cat]".split("[:\\[\\]]+");
   for(String s : list)
       System.out.println(s);

答案 2 :(得分:0)

单字符分隔符很容易被分割:String.split()函数将分割为字符或字符串。它们完全符合StringTokenizer的功能,但使用更清晰的语法。也就是说,String[] items = myString.split(",")看起来比

更清洁
StringTokenizer st = new StringTokenizer(myString, ","); 
while(st.hasMoreTokens()){
    myList.add(st.nextToken();
}

(将来使用split就是我所说的。)

然而,看起来你处于一个稍微复杂的情况,你需要在[左侧和]右边的边界。这需要正则表达式和捕获组。像/\[(.*)\]/

这样的东西

CSV(逗号分隔值)对于简单的表格数据是常见的,并且格式甚至在一定程度上标准化。如果要表示更复杂的对象,则可以使用JSON或SOAP。如果您只使用Java存储,请查看Java的内置序列化功能。

由于您在本地使用它,并且可能正在保存某种Java对象来表示它,因此一种方法是在表示数据的任何对象中实现Serializable

如果您不喜欢这样,我会使用JSON,因为它看起来像是在做某种树形结构。

答案 3 :(得分:0)

由于您可以控制文件格式,我建议使用制表符分隔。许多其他程序(例如Excel)将读取制表符分隔。所以文件看起来如下(\ t代表标签)

AB523\tjoe, pierre\tcharlie\tdogs,cat
ZZ883\tronald, zigomarre\tpele

注意 - 您不能使用另一种常见格式的逗号分隔(CSV),因为逗号是字符串中的合法值。同样,如果制表符是字符串中的合法字符,则制表符分隔将出现问题。

与其他人一样,String.split()是一种解析文件的好方法。

答案 4 :(得分:0)

如果要生成数据文件,请使用CSV(对于简单线性数据)或Json(对于结构化数据)甚至XML(对结构化数据进行大量处理)等标准格式生成数据文件。