【问题标题】:Java scanner delimiter detects ';' but not '\n'Java 扫描仪定界符检测到 ';'但不是'\n'
【发布时间】:2019-06-30 23:27:59
【问题描述】:

我有一个格式化的文本文件,我需要从中提取信息并将其放入类 Item 中的相应成员变量中(1 行文本 = 1 个 Item)。 我正在使用扫描仪和分隔符,但它只能识别; 分隔信息,而不能识别新行。

我尝试了几种不同的正则表达式,我最新的一个在下面,我只指定了我知道即将出现的分隔符。我也试过正则表达式 [;\\n] 。我唯一的结论是扫描仪处理换行符的方式与其他不同(这是有道理的,我知道它具有基于换行符的功能)。

这里是文本文件格式

1000;Knock Bits;88;12.67;8015
1001;Widgets;10;35.50;8004
1002;Grommets;20;23.45;8001

这是我的代码的样子

while (scan.hasNext())
{           
Item item = new Item();
scan.useDelimiter("[;]");

item.setID(scan.nextInt());
item.setName(scan.next());
item.setQuantity(scan.nextInt());
item.setPriceInCents((int) scan.nextFloat()*100);

scan.useDelimiter("\\n");
item.setSupplierID(scan.nextInt()); 
}

除了最后一行使用nextInt() 获取供应商ID 之外,上述所有代码都有效。我知道我可以用

替换该行
item.setSupplierID(Integer.parseInt(scan.nextLine()));

但这有点难看,应该有一种方法可以使用正则表达式来做到这一点,而不必专门为最后一个词定制一行。最好在整个循环中只使用一个分隔符。

【问题讨论】:

  • 你试过scan.useDelimiter("[;\n"]);吗?
  • 是的,还是不行。
  • 如果你的行尾不是\n,它可能不起作用,这是可能的。请改用"[;\\s]+"

标签: java regex java.util.scanner


【解决方案1】:

使用 scanner.useDelimiter("[;\n]");scanner.useDelimiter("[;\r\n]"); 工作Windows 和 Linux 系统。

在while循环之外调用它:

    scanner.useDelimiter("[;\r\n]");

    while (scanner.hasNext()) {
        Item item = new Item();
        item.setID(scanner.nextInt());
        item.setName(scanner.next());
        item.setQuantity(scanner.nextInt());
        item.setPriceInCents((int) scanner.nextFloat()*100);
        item.setSupplierID(scanner.nextInt());
    }

如果按照 mypetlion 的建议使用 \R:scanner.useDelimiter(";|\\R");

【讨论】:

  • 为了完全不可知,您可以将\r\n 替换为\R。在 Java 8 中介绍了 Java 的模式语法。
  • 1;2\r\n3;4 之类的数据使用分隔符[;\r\n] 会失败,因为字符类[...] 描述了它可以匹配的单个 字符的潜在集合。换句话说,each \r\n 被视为 separate 分隔符,这意味着扫描器会认为 \r\n 处有一个元素(空字符串)(在\r\n 之间)。改用\R 解决了这个问题(但它必须在字符类之外使用,因为它不代表单个字符,还代表\r\n sequence)。
  • 这解决了问题。我想换行符是\r。为了在没有太多麻烦的情况下完全不可知,我想你可以想出一个正则表达式来包含所有数字、空格、制表符,并留下任何其他字符(标点符号、\n、\r 等)作为分隔符。这将允许逗号和其他分隔符起作用。
  • 稍微不相关的问题,\n\r 和 \\n\\r 都工作并且做同样的事情。这怎么可能?除非他们在这种情况下巧合地做了同样的事情?
【解决方案2】:

读取整行然后使用 string.split(";") 获取元素

List<Map<String,Object>> items = new ArrayList<>();
    try {
        Scanner scanner = new Scanner(new File(ClassLoader.getSystemResource("stats.txt").getFile()));
        while (scanner.hasNext()){
            String[] itemString = scanner.nextLine().split(";");
            Map<String,Object> item = new HashMap<>();
            item.put("id",Integer.parseInt(itemString[0]));
            item.put("name",itemString[1]);
            item.put("quant",Integer.parseInt(itemString[2]));
            item.put("price",Float.parseFloat(itemString[3]));
            item.put("suplierId",Integer.parseInt(itemString[4]));
            items.add(item);

        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    items.forEach(i->{
        i.forEach((key, value) -> System.out.println(key + " : " + value));
        System.out.println();
    });

您可以只填充对象解析值而不是 Map

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-05
    • 1970-01-01
    • 2015-11-27
    • 2023-03-20
    • 2014-04-03
    相关资源
    最近更新 更多