0

当输入文件中出现错误时,是否可以找出扫描仪在输入文件的哪一行失败?

以下代码始终打印出阅读器中的总行数,而不是发生错误的行号:

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; 
    }
}
4

1 回答 1

3

AScanner不跟踪行号或字符号。

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

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

如果nextInteger()方法调用失败,则报告的“当前位置”FilterReader可能是检测到错误整数的流位置之后的许多字符。

在最坏的情况下,这种回绕可以带您回到行边界……取决于您如何配置分隔符。因此(理论上)即使是行号也无法确定地跟踪。


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

于 2013-06-23T13:20:54.510 回答