【问题标题】:Where to put the try catch blocks [closed]在哪里放置try catch块[关闭]
【发布时间】:2016-07-02 22:45:18
【问题描述】:

我有一个按钮,可以将文件列表放入数组中,然后为每个文件调用 WwritefiletoDB 函数:

private void BtnImportActionPerformed(java.awt.event.ActionEvent evt) {                                          
    // Create array to store filenames
    List<String> filenames = new ArrayList<String>();
    JTextFiles.append("*** Current Files Processing ***\n");
    File dir = new File(TextFieldDirectory.getText());
    File[] files = dir.listFiles(new FilenameFilter() {
        public boolean accept(File dir, String name) {
            return name.toLowerCase().endsWith(".pdf");
        }
    });
    for (File file : files) {
        if (file.isFile()) {
            JTextFiles.append(file.getAbsolutePath() + "\n");
            try {
                writefiletoDB(file.getAbsolutePath());
            } catch (SQLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    JTextFiles.append("*** Finished Processing ***\n");
}

注意 try catchblocks。

writefiletoDB 方法有这样的代码:

public void writefiletoDB(String currentfile) throws SQLException, IOException {
    //System.out.println("This is current file:" + currentfile);
    PDDocument pdfDocument = PDDocument.load(new File(currentfile));
    PDDocumentCatalog docCatalog = pdfDocument.getDocumentCatalog();
    PDAcroForm acroForm = docCatalog.getAcroForm();
    List fields = acroForm.getFields();
    PDField EventNo = acroForm.getField("EventNo");
    System.out.println("Event String Length: " + EventNo.getValueAsString().length());
    // If event number too short - then skip record
    if (EventNo.getValueAsString().length() != 10) {
        //JOptionPane.showMessageDialog(null, currentfile +" record was skipped - invalid EventNo = " +EventNo.getValueAsString());
        JTextFiles.append("The above file skipped - the event number was incorrect length\n");
        pdfDocument.close();
        return;
    };

    Iterator fieldsIter = fields.iterator();
    // Create Hashmap "pdf" storing PDF field names & values
    Map<String, String> pdf = new HashMap<String, String>();
    while (fieldsIter.hasNext()) {
        PDField field = (PDField) fieldsIter.next();
        // Next line removes braces for dropdowns and any leading whitespace
        pdf.put(field.getPartialName(), field.getValueAsString().replaceAll("[\\[\\]]", "").trim());
    }

    //Create list "columns" to store field names from Database
    List<String> columns = new ArrayList<String>();

    Connection conn = null;
    Statement stmnt = null;
    try { 
        //Connect to DB
       conn = DriverManager.getConnection("jdbc:ucanaccess://" + TextFieldDatabase.getText());
       stmnt = conn.createStatement();  
    } catch (SQLException se) {
             JOptionPane.showMessageDialog(null, "A SQL Error: " +se, "SQL ERROR", JOptionPane.ERROR_MESSAGE);            
             return;
    }


    // Check If Event Number already exists in DB - if so then exit
    System.out.println("Checking if event exists");
    PreparedStatement psEvent = conn.prepareStatement("SELECT EventNo FROM test WHERE EventNo = ?");
    psEvent.setString(1, EventNo.getValueAsString());
    ResultSet rsEvent = psEvent.executeQuery();

    if (!rsEvent.next()) {
        System.out.println("Result set is empty");
    } else {
        JTextFiles.append("The above record already exists - skipping\n");
        pdfDocument.close();
        return;
    }

    // Get a list of column names from database
    ResultSet rs = stmnt.executeQuery("SELECT * FROM test WHERE False");
    ResultSetMetaData rsmd = rs.getMetaData();
    //System.out.println("Column names as reported by ResultSetMetaData:");

    // Add the column names from database to List columns
    for (int i = 1; i <= rsmd.getColumnCount(); i++) {
        System.out.println(rsmd.getColumnName(i));
        // Store the column names from DB in list columns (via result set rsmd)
        columns.add(rsmd.getColumnName(i));
    }

    // col and val strings to be built colname,colname and ?,?,?,? etc
    // for sql prepared statement into DB
    StringBuilder col = new StringBuilder();
    StringBuilder val = new StringBuilder();
    String separator = "";
    for (String c : columns) {
        if (pdf.containsKey(c)) {
            col.append(separator).append(c);
            val.append(separator).append("?");
            separator = ",";
        }
    }

    // Insert into DB SQL Statement
    String sql = String.format("INSERT INTO test (%s) VALUES (%s)", col.toString(), val.toString());

    System.out.println(
            "This is sql statement: " + sql);
    try (PreparedStatement insert = conn.prepareStatement(sql)) {
        //Insert position in statement
        int pos = 0;
        //Second iterations: Bind the values to the statement *** colums is names of cols fromDB
        for (String c : columns) {
            //Your PDF has a matching formfield ** pdf is hashmap <string,string>
            if (c.toLowerCase().contains("date")) {
                System.out.println("A Date field has been found: " +c);
                DateTimeFormatter formatter = DateTimeFormat.forPattern("dd/MM/yyyy kk:mm");
                DateTime startdt = formatter.parseDateTime(pdf.get("DateStart") +" " +pdf.get("TimeStart"));
                long millis = formatter.parseMillis(pdf.get("DateStart") +" " +pdf.get("TimeStart"));
                Timestamp timeStamp = new Timestamp(millis);
                insert.setTimestamp(++pos, timeStamp);
            }
            if (pdf.containsKey(c) && !c.toLowerCase().contains("date")) {
                insert.setString(++pos, pdf.get(c));
            }
        }
        insert.executeUpdate();
    } catch (SQLException e) {
        //JFrame frame;
        JOptionPane.showMessageDialog(null, "A SQL Error: " +e, "SQL ERROR", JOptionPane.ERROR_MESSAGE);            
        e.printStackTrace();
    }

    pdfDocument.close();
}

注意 try catch 块,大约在第 30 行。如果它产生错误,return 语句会中断并返回到调用方法 BtnImportActionPerformed 并且循环调用下一个文件产生另一个错误。

我需要一种方法来打破 writefiletoDB 并停止 BtnImportActionPreformed。

有没有办法在 BtnImportActionPreformed 中处理 writefiletoDB 异常?或两者兼而有之。

最好的方法是什么 - 我想让代码更健壮。

谢谢

阿尔

【问题讨论】:

  • 我不确定我是否理解正确,但我理解的是你只需要在你的 catch 块中添加一个 break; 语句。

标签: java return try-catch controls


【解决方案1】:

将您的示例简化为相关结构,代码是这样做的:

void BtnImportActionPerformed() {
    for(int i = 0l i < 10; i++) {
        writefiletoDB();
    }
}

void writefiletoDB() {
    try {
        doSomething();
    } catch (SomeException e) {
        return;
    }
}

由于异常在内部方法中被捕获并处理,因此外部方法无法知道发生了什么问题。如果您希望外部方法知道发生了异常,请使用与内部方法相同的模式。捕获抛出的异常。像这样的:

void BtnImportActionPerformed() {
    for(int i = 0l i < 10; i++) {
        try {
            writefiletoDB();
        } catch (SomeException e) {
            // do anything else?
            return;
        }
    }
}

void writefiletoDB() throws SomeException {
    try {
        doSomething();
    } catch (SomeException e) {
        // log it?  something else?
        throw e;
    }
}

如果外部方法可以完成所有异常处理,您甚至可以完全跳过内部 try/catch。您只需在 writefiletoDB 方法上声明可能的异常即可。

【讨论】:

  • 是的,所以你在内部方法中捕获异常然后再次抛出它以被外部方法捕获?我没有意识到抛出异常(但我现在这样做了)所以我不能只在 BtnImportActionPerformed 中捕获异常吗?并且在 writefiletoDB 中没有处理?
  • @AlGrant:这对你来说确实是一个逻辑问题。确实可以在调用堆栈的任何地方捕获异常。它应该被捕获的地方是它可以被有意义地处理的地方。有时这可能涉及多个捕获,因为每个方法都有自己的方法在该方法的上下文中部分处理它,可能会在重新抛出异常之前将信息添加到异常中。有时不会。
  • 谢谢 - 现在工作得很好。
【解决方案2】:

有多种方法可以解决这个问题,我会根据你的逻辑来选择。

  • 不要捕获任何异常,让BtnImportActionPerformed的调用者捕获。
  • 将 try catch 放在 BtnImportActionPerformed 的 for 循环周围,这样一旦引发异常,您就会退出循环。请删除 for 循环中的 try/catch。
  • writefiletoDB 返回成功/失败而不是异常。在BtnImportActionPerformed 基于成功/失败你可以退出循环。

【讨论】: