序章
開いているファイルが多すぎるという例外に関する多くの情報をWeb で見つけましたが、この奇妙なケースを解決できませんでした。私が読んだように、OSで定義されたプロセスによって開かれたファイル記述子の数を超えると、例外がスローされます。これらのファイルの性質はさまざまです。ファイルは、ソケット、ドキュメントなどである可能性があります。そして、Java アプリケーションに実装したファイルを開くための堅牢で安全な方法を見つけました。
このアプリケーションは、ボイラーパイプアルゴリズムを使用して Web ページをダウンロードする短いプログラムです。このようにして、そのサイトの最も代表的なコンテンツを取得します。そして、それを適切な形式 ( TREC 形式) でディスクに書き込みます。これらの Web サイトの URL は、JDBC コネクタを使用してアクセスする MySQL データベースから取得されます。
したがって、例外は 3 つの異なる場所からスローされる可能性があると思います。
- データベースへの接続
- Web サイトへの HTTP 接続
- ファイルのオープンと書き込み
とはいえ、私が言ったように、私はそれらのファイルを開いて書き込む正しい方法を使用していると思います。
問題
処理する URL が数千あり、しばらくすると例外がスローされます (これにより、デバッグも非常に困難になります... )。それが問題かどうかはわかりませんが、URL はさまざまなカテゴリに分類されており、プロセス全体を高速化するためにプログラムのさまざまなインスタンスを実行しています。カテゴリは重複しないので問題ありません。
コード
読みやすくするために、コードのこれら 3 つの部分だけを簡略化して示します。
データベースへのアクセス
// Connect to database Connection dbconn = null; try { String dbUrl = "jdbc:mysql://" + dbServer + "/" + dbName; Class.forName ("com.mysql.jdbc.Driver").newInstance (); dbconn = DriverManager.getConnection(dbUrl, dbUser, dbPass); System.out.println ("Database connection established"); } catch (Exception e) { e.printStackTrace(); System.err.println ("Cannot connect to database server"); System.exit(-1); } System.out.println(" Downloading category: " + category); Statement s = null; try { s = dbconn.createStatement(); } catch (SQLException e) { System.err.println ("Error on creating the statement"); System.exit(-1); e.printStackTrace(); } String q = "SELECT resource,topic FROM " + "content_links " + "WHERE topic LIKE 'Top/" + category + "%';"; try { s.executeQuery(q); } catch(Exception e) { System.err.println ("Error on executing the SQL statement"); System.exit(-1); e.printStackTrace(); } ResultSet rs = null; try { rs = s.getResultSet (); } catch (SQLException e) { System.err.println ("Error on getting the result set"); System.exit(-1); e.printStackTrace(); } int count = 0, webError = 0; // work with the result set try { while (rs.next ()) { // MAIN LOOP } } catch (SQLException e) { System.err.println ("Error on getting next item"); System.exit(-1); e.printStackTrace(); } // Close connection to database if (dbconn != null) { try { dbconn.close (); System.out.println (" Database connection terminated"); } catch (Exception e) { /* ignore close errors */ } }
HTTP 接続、サイトのタイトルとボイラーパイプ フィルターの抽出
try { String title = ""; org.jsoup.nodes.Document doc = Jsoup.connect(urlVal).get(); for (Element element : doc.select("*")) { if (element.tagName().equalsIgnoreCase("title")) { title = element.text(); } if (!element.hasText() && element.isBlock()) { element.remove(); } } String contents = ""; contents = NumWordsRulesExtractor.INSTANCE.getText(doc.text()); storeFile(id, urlVal, catVal, title, contents); } } catch (BoilerpipeProcessingException e) { System.err.println("Connection failed to: " + urlVal); } catch (MalformedURLException e1) { System.err.println("Malformed URL: " + urlVal); } catch(Exception e2) { System.err.println("Exception: " + e2.getMessage()); e2.getStackTrace(); }
ファイルの書き込み
private static void storeFile(String id, String url, String cat, String title, String contents) { BufferedWriter out = null; try { out = new BufferedWriter( new OutputStreamWriter( new FileOutputStream( new File(path + "/" + id + ".webtrec")),"UTF8")); // write in TREC format out.write("..."); } catch (IOException e) { System.err.println("Error: " + e.getMessage()); e.printStackTrace(); } finally { try { out.close(); } catch (IOException e) { System.err.println("Error: " + e.getMessage()); e.printStackTrace(); } }