2013-06-23 17 views
0

当输入文件中有错误时,可以找出扫描仪输入文件的哪一行失败?有没有办法获得java.util.Scanner失败的输入文件的行号(和列号)?

下面的代码总是打印出总线在读取器,而不是行号的错误发生:

import java.io.LineNumberReader; 
import java.io.StringReader; 
import java.util.NoSuchElementException; 
import java.util.Scanner; 
import org.junit.Test; 

public class ScannerTests { 

    static private final String text = "FUNCTION_BLOCK Unnamed_project\n\tVAR_INPUT\n\t\tUnnamed_variable1::REAL;\n\tEND_VAR\nEND_FUNCTION_BLOCK"; 

    @Test 
    public void scannerLineNumberFailedTest() { 

     LineNumberReader reader = new LineNumberReader(new StringReader(text)); 

     int lineNumber = -1; 

     try { 
      Scanner sc = new Scanner(reader); 
      sc.useDelimiter("\\s*\\b\\s*"); 

      sc.next("(?i)FUNCTION_BLOCK"); 
      String blockName = sc.next(); 
      assert sc.hasNext("(?i)VAR_INPUT"); 
      sc.next("(?i)VAR_INPUT"); 
      String variableName = sc.next(); 
      sc.next(":");      // line of failure - got a unexpected '::' 
      String type = sc.next("\\w+"); 
      sc.next(";"); 
      sc.next("(?i)END_VAR");    
      sc.next("(?i)END_FUNCTION_BLOCK"); 

      assert "Unnamed_project".equals(blockName); 
      assert "Unnamed_variable1".equals(variableName); 
      assert "REAL".equals(type); 

      sc.close(); 
     } catch (NoSuchElementException ex) { 

      lineNumber = reader.getLineNumber() + 1; 
      System.err.println("Error in line: " + lineNumber); 
     } 

     assert lineNumber == 3; 
    } 
} 
+1

看起来你正在尝试使用扫描仪来解析编程语言(或DSL)的文本。这不是一个好主意,您应该使用像ANTLR这样的解析器生成器。 –

回答

3

Scanner不追踪行号或字符数目。

你可以尝试使用自定义的FilterReader来实现这一点,它可以对行和字符进行计数,但我认为这在所有情况下都不准确。它会告诉你扫描仪在流中的距离有多远,但它不能考虑到扫描仪可以在hasNext方法中预读多个字符,然后使用不同的方法读回输入next方法。例如:

if (sc.hasNext("[A-Z ]+")) { 
    sc.nextInteger(); 

如果nextInteger()方法调用失败,所报告的FilterReader“当前位置”可能是人物众多过去在检测到非整数的流位置。

在最糟糕的情况下,这种绕回可能会使您回到线路边界......取决于您如何配置分隔符。所以(理论上)甚至行号都不能确定地被跟踪。


在所有情况下100%的准确跟踪行和字符数的唯一办法是实现自己的输入解析系统,通过其所有的输入流的向前和向后运动的跟踪这些东西本身...光标。

+0

感谢您的回答,但它没有回答这个问题。 – Tuto

+2

@Tuto - 实际上,它的确如此。这只是它不是你想听到的答案。 –

+0

扩展的答案是我可以接受的答案。可能不足以在扫描器周围编写包装,最好为此打一个解析器生成器。 – Tuto

相关问题