【问题标题】:java regex linejava正则表达式行
【发布时间】:2009-06-18 12:27:52
【问题描述】:

在 java 中,我想逐行读取文件并将该行打印到输出。 我想用正则表达式解决这个问题。

while (...)
{
  private static java.util.regex.Pattern line = java.util.regex.Pattern.compile(".*\\n");
  System.out.print(scanner.next(line));
}

代码中的正则表达式不正确,因为我得到 InputMismatchException。 我在这个正则表达式上工作了 2 个小时。请帮忙。

使用正则表达式 powertoy,我看到 ".*\n" 是正确的。但是我的程序运行不正确。

整个来源是:

/**
 * Extracts the points in the standard input in off file format to the standard output in ascii points format.
 */

 import java.util.regex.Pattern;
 import java.util.Scanner;

class off_to_ascii_points 
{
    private static Scanner scanner = new Scanner(System.in);    
    private static Pattern fat_word_pattern = Pattern.compile("\\s*\\S*\\s*");
    private static Pattern line = Pattern.compile(".*\\n", Pattern.MULTILINE);

    public static void main(String[] args) 
    {
        try
        {
            scanner.useLocale(java.util.Locale.US);

                    /* skip to the number of points */
            scanner.skip(fat_word_pattern);

            int n_points = scanner.nextInt();

                    /* skip the rest of the 2. line */
            scanner.skip(fat_word_pattern); scanner.skip(fat_word_pattern);

            for (int i = 0; i < n_points; ++i)
            {
                    System.out.print(scanner.next(line));
                      /*
                      Here my mistake is. 
                      next() reads only until the delimiter, 
                      which is by default any white-space-sequence. 
                      That is next() does not read till the end of the line 
                      what i wanted.

                      Changing "next(line)" to "nextLine()" solves the problem.
                      Also, setting the delimiter to line_separator 
                      right before the loop solves the problem too.
                      */
            }

        }
        catch(java.lang.Exception e)
        {
            System.err.println("exception");
            e.printStackTrace();
        }
    }
}

示例输入的开头是:

OFF
4999996 10000000 0
-28.6663 -11.3788 -58.8252 
-28.5917 -11.329 -58.8287 
-28.5103 -11.4786 -58.8651 
-28.8888 -11.7784 -58.9071 
-29.6105 -11.2297 -58.6101 
-29.1189 -11.429 -58.7828 
-29.4967 -11.7289 -58.787 
-29.1581 -11.8285 -58.8766 
-30.0735 -11.6798 -58.5941 
-29.9395 -11.2302 -58.4986 
-29.7318 -11.5794 -58.6753 
-29.0862 -11.1293 -58.7048 
-30.2359 -11.6801 -58.5331 
-30.2021 -11.3805 -58.4527 
-30.3594 -11.3808 -58.3798 

我首先跳到数字 4999996,它是包含点坐标的行数。这些行是我正在尝试写入输出。

【问题讨论】:

    标签: java regex


    【解决方案1】:

    我建议使用

    private static Pattern line = Pattern.compile(".*");
    
    scanner.useDelimiter("[\\r\\n]+"); // Insert right before the for-loop
    
    System.out.println(scanner.next(line)); //Replace print with println
    

    为什么您的代码不能按预期工作:

    这与您使用的 Scanner 类以及该类的工作方式有关。

    javadoc 声明:

    扫描器将其输入分解为令牌 使用分隔符模式,通过 默认匹配空格。

    这意味着当您调用 Scanner 的其中一个 .next* 方法时,扫描器会读取指定的输入,直到遇到下一个分隔符。

    所以您对scanner.next(line) 的第一次调用开始读取以下行

    -28.6663 -11.3788 -58.8252 
    

    并停在 -28.6663 之后的空格处。然后它检查令牌 (-28.6663) 是否与您提供的模式 (.*\n) 匹配,而后者显然不匹配 (-28.6663)。这就是为什么。

    【讨论】:

      【解决方案2】:

      如果您只想将文件打印到标准输出,为什么要使用正则表达式?如果你知道你总是想跳过前两行,有更简单的方法来完成它。

      import java.util.Scanner;
      import java.io.File;
      
      public class TestClass {
          public static void main(String[] args) throws Exception {
              Scanner in=new Scanner(new File("test.txt"));
              in.useDelimiter("\n"); // Or whatever line delimiter is appropriate
              in.next(); in.next(); // Skip first two lines
              while(in.hasNext())
                  System.out.println(in.next());
          }
      }
      

      【讨论】:

      • 我必须读入行数。这是 2. 行中的第一个单词。
      【解决方案3】:

      您必须将Pattern 切换到多行模式。

      line = Pattern.compile("^.*$", Pattern.MULTILINE);
      System.out.println(scanner.next(line));
      

      【讨论】:

      • MULTILINE 也不起作用。 $ 字符对我来说还不够,因为我希望将 new_line 字符包含在匹配的字符串中。
      【解决方案4】:

      默认情况下,扫描仪使用空白作为分隔符。在第一次跳过后读取该行之前,您必须将分隔符更改为新行。您需要更改的代码是在 for 循环之前插入以下行:

      scanner.useDelimiter(Pattern.compile(System.getProperty("line.separator")));

      并更新 Pattern 变量行如下:

      private static Pattern line = Pattern.compile(".*", Pattern.MULTILINE);

      【讨论】:

      • 不依赖“line.separator”属性。任何给定的文件都可以使用任何样式的行分隔符,甚至是两种以上样式的混合。 Scanner 的 hasNextLine() 和 nextLine() 方法考虑到了这一点。
      【解决方案5】:

      感谢大家的帮助。

      现在我明白我的错误了:

      API 文档指出,Scanner 类的每个 nextT() 方法首先跳过分隔符模式,然后尝试读取 T 值。但是它忘记说每个 next...() 方法只读取直到第一次出现分隔符!

      【讨论】:

        猜你喜欢
        • 2015-12-29
        • 2017-09-28
        • 1970-01-01
        • 2016-09-28
        • 2013-01-18
        • 2012-01-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多