【问题标题】:How can exception message overtake an executed printed line异常消息如何超过已执行的打印行
【发布时间】:2019-06-18 08:26:39
【问题描述】:

我从一个用“;”分隔的 .csv 文件中读取字段分号。我写了例外来处理可能的偏差。但是如果出现异常,NetBeans 会在最后一行之前读出错误消息。

这是输出的样子:

我不明白代码中的后面一行怎么可能以前打印出来。这是我的全部代码:

public static void reader(String fileName) throws IOException {
    try (BufferedReader br = new BufferedReader(new FileReader(fileName))) {
        String line;
        List<String> lineHolder = new ArrayList<>();
        StringTokenizer divider;
        String formatter = "%2s|%-30s|%-30s|%10s|%n";

        String separator = "----------";
        System.out.format("ID|%-30s|%-30s|birth date|%n", "name", "email");
        System.out.print("--+" + separator + separator + separator 
                + "+" + separator + separator + separator + "+" 
                + separator + "+\n");

        while ((line = br.readLine()) != null){
            if (line.startsWith("#", 0))
                continue;
            if (!line.contains(";")) {
                throw new IOException("too less data or not proper delimiter");
            }
            divider = new StringTokenizer(line, ";");
            lineHolder = arrayFiller(divider);
            dataChecker(lineHolder, line);
            System.out.format(formatter, lineHolder.get(0), lineHolder.get(1)
                , lineHolder.get(2), lineHolder.get(3));
        }
    } catch (FileNotFoundException ex) {
        System.err.println("The file not found.");
    } catch (IOException ex){
        System.err.println(ex.getMessage());
    }
    System.out.print("\n");
}

public static ArrayList<String> arrayFiller(StringTokenizer divider) {
    ArrayList<String> lineHolder = new ArrayList<>();
    while (divider.hasMoreTokens()) {
        lineHolder.add(divider.nextToken());
    }
    return lineHolder;
}

这些是例外:

public static void dataChecker(List<String> lineHolder, String line) throws IOException {
    if (lineHolder.size() < 4) {
        throw new IOException("too less data or not proper delimiter");
    } else if (lineHolder.size() > 4) {
        throw new IOException("too much data");
    } else if (lineHolder.get(0).length() > 2 
            || !Pattern.matches("[0-9]+", lineHolder.get(0))) {
        throw new IOException("Error during reading the file: "
                + "not proper ID field format");
    } else if (lineHolder.get(1).length() > 30 
            || !Pattern.matches("[a-zA-ZíÍöÖüÜóÓőŐúÚűŰáÁéÉ. ]+", lineHolder.get(1))) {
        throw new IOException("Error during reading the file: "
                + "not proper Name field format");
    } else if (lineHolder.get(2).length() > 30 
            || !Pattern.matches("[a-zA-Z0-9@. ]+", lineHolder.get(2))) {
        throw new IOException("Error during reading the file: "
                + "not proper Email field format");
    } else if (lineHolder.get(3).length() > 10 || dateFormatter(lineHolder.get(3))) {
        throw new IOException("Error during reading the file: "
                + "not proper Birth date field format");
    } 
}

public static boolean dateFormatter(String datum) {
    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    try {
        LocalDate changedDate = LocalDate.parse(datum, dtf);
        return false;
    } catch (DateTimeParseException ex) {
        return true;
    }
}

还有源文件:

#ID;name;email;birth date
1,Jakob George,gipszjakab@gmail.com,1981-11-23
2;Susan Smith;usa@gmail.com;1982-12-01
3;Poul Drake;gameover@gmail.com;1990-01-02
4;Isaac Wheather;ruck%sack@freemail.hu;1988-01-22
5;George T. Benson;bigman@hotmail.com;1977-08-12

我试图将方法(异常持有者)放入reader() 方法中,但结果相同。这怎么可能?我做错了什么?

【问题讨论】:

  • matches("[a-zA-ZíÍöÖüÜóÓőŐúÚűŰáÁéÉ. ] 那些奇怪的字符是什么?
  • 这些是匈牙利语的东欧字符。最后是点和空格。
  • 好的。您的代码运行良好。更新您的 csv 文件。详情请查看我的回答。
  • 我只是希望你编造了那些邮件地址!
  • 脱离上下文,但 eclipse 在这种情况下工作正常。

标签: java string exception-handling io file-read


【解决方案1】:

错误消息通过不同的输出流打印。标准输出流stdout 用于正常记录/输出,错误(通过 System.err.println)转到stderr。您的控制台/终端同时显示两者,但它们不会等待对方完成打印。

编辑:也许this 也有帮助。

EDIT2:如果您将错误更改为打印到文件,您将在控制台/终端中丢失错误输出。但也许这对你没问题?像这样:

//set err out to print to file
PrintStream ps = new PrintStream("err.log");
System.setErr(ps);

//cause exception for testing it
String s = null;
s.length();

如果您希望将两个错误和标准输出打印到控制台/终端,则无法控制两个流的时间,因为每个打印行都是独立的操作。

【讨论】:

  • 谢谢。那是我不知道的解决方案。该链接也很有帮助。除此之外,我还不明白如何避免这种相反的情况。
  • 我添加了示例代码以完全避免错误输出到控制台,但我认为如果您想将 both 打印到控制台,则无法控制两者的时间流,因为每个打印行都是一个独立的操作。
  • 完美解决方案。通过添加的示例,我清楚地理解了。谢谢。
【解决方案2】:
    String separator = "----------";
    System.out.format("ID|%-30s|%-30s|birth date|%n", "name", "email");
    System.out.print("--+" + separator + separator + separator 
            + "+" + separator + separator + separator + "+" 
            + separator + "+\n");
    System.out.flush();
    while ((line = br.readLine()) != null)

由于 System.out 和 System.err 来自不同的输出流,它们不会等待对方完成。在打印语句之后立即清除缓冲区内存会解决问题。

【讨论】:

  • 是的,它的工作原理是这样的,持续一段时间循环。内部(当我从第一行删除逗号时)在第 4 行丰富时发生相同的情况。错误信息跳转到第 3 行之前。如何在循环内使用?
猜你喜欢
  • 1970-01-01
  • 2011-07-14
  • 1970-01-01
  • 1970-01-01
  • 2015-05-31
  • 2013-04-30
  • 1970-01-01
  • 2013-03-30
  • 2021-03-19
相关资源
最近更新 更多