2011-04-02 79 views
0

我是一個Java新手,似乎無法弄清楚爲什麼這個原始的20分鐘的應用程序正在拋出該異常。爲什麼我一直使用這段代碼得到一個ArrayIndexOutOfBoundsException?

基本上我解析了一個192MB(是,192MB)製表符分隔的文本文件並將內容存儲到MongoDB中。

package get_alternatenames; 

import java.io.BufferedReader; 
import java.io.FileReader; 

import com.mongodb.Mongo; 
import com.mongodb.DB; 
import com.mongodb.DBCollection; 
import com.mongodb.BasicDBObject; 
import com.mongodb.DBObject; 
import com.mongodb.DBCursor; 
import java.util.Set; 

/** 
* 
* @author cbmeeks 
*/ 
public class Main { 

    /** 
    * @param args the command line arguments 
    */ 
    public static void main(String[] args) throws Exception { 
     String alternateNamesFileName = "/Users/cbmeeks/Projects/GetData/geonames/alternateNames.txt"; 
     String line; 

     // MongoDB 
     Mongo m = new Mongo("localhost", 27017); 
     DB db = m.getDB("mydb"); 

     // Build AlternateNames 
     DBCollection altNames = db.getCollection("alternatenames"); 
     BufferedReader bReader = new BufferedReader(new FileReader(alternateNamesFileName)); 

     int isPreferredName = 0; 
     int isShortName = 0; 
     int lines = 0; 

     System.out.println("Starting AlternateNames import..."); 

     while ((line = bReader.readLine()) != null) { 
      String l[] = line.split("\t"); 
      BasicDBObject altName = new BasicDBObject(); 
      altName.put("alternateNameId", l[0]); 
      altName.put("geonameId", l[1]); 
      altName.put("isoLanguage", l[2]); 
      altName.put("alternateName", l[3]); 

      isPreferredName = 0; 
      isShortName = 0; 

      try { 
       if (l[4] != null) { 
        isPreferredName = Integer.parseInt(l[4]); 
       } 
      } catch (ArrayIndexOutOfBoundsException ex) { 
       isPreferredName = 0; 
      } catch (Exception ex) { 
       isPreferredName = 0; 
      } 

      try { 
       if (l[5] != null) { 
        isShortName = Integer.parseInt(l[5]); 
       } 
      } catch (ArrayIndexOutOfBoundsException ex) { 
       isShortName = 0; 
      } catch (Exception ex) { 
       isShortName = 0; 
      } 

      altName.put("isPreferredName", isPreferredName); 
      altName.put("isShortName", isShortName); 

      altNames.insert(altName); 

      lines++; 
     } 

     bReader.close(); 
     System.out.println("Number of lines parsed: " + lines); 

     System.out.println("Creating indexes..."); 
     altNames.createIndex(new BasicDBObject("geonameId", 1)); 
     altNames.createIndex(new BasicDBObject("isoLanguage", 1)); 
     altNames.createIndex(new BasicDBObject("alternateName", 1)); 

    } 
} 

我知道這不是世界上最美的代碼。實際上它似乎一直工作到最後。它成功進口540萬條記錄,然後結束:

Starting AlternateNames import... 
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException 
Java Result: 1 
BUILD SUCCESSFUL (total time: 2 minutes 58 seconds) 

我似乎無法找到問題所在。我試圖搜索文本文件來發現一個問題,但在192MB,似乎沒有任何東西能夠處理它,除了MacVIM,我無法完全理解該程序。大聲笑

但我相信它沒有完成文件。當我轉到文本文件中導入的最後一條記錄時(基於MongoDB中的記錄計數),看起來看起來很好...但我可能錯過了一些東西。

有什麼建議嗎?

謝謝。

BTW,榮譽給Java進行解析在3分鐘內該文本文件...

+0

您應該知道哪一行拋出異常,您可以通過查看行號然後檢查代碼來了解它。 – Jack 2011-04-02 03:54:42

回答

0

這是我更正的代碼,它的工作原理。感謝所有提示。

package get_alternatenames; 

import java.io.BufferedReader; 
import java.io.FileReader; 

import com.mongodb.Mongo; 
import com.mongodb.DB; 
import com.mongodb.DBCollection; 
import com.mongodb.BasicDBObject; 
import com.mongodb.DBObject; 
import com.mongodb.DBCursor; 
import java.util.Set; 

/** 
* 
* @author cbmeeks 
*/ 
public class Main { 

    /** 
    * @param args the command line arguments 
    */ 
    public static void main(String[] args) throws Exception { 
     String alternateNamesFileName = "/Users/cbmeeks/Projects/GetData/geonames/alternateNames.txt"; 
     String line; 

     // MongoDB 
     Mongo m = new Mongo("localhost", 27017); 
     DB db = m.getDB("MyDB"); 

     // Build AlternateNames 
     DBCollection altNames = db.getCollection("alternatenames"); 
     BufferedReader bReader = new BufferedReader(new FileReader(alternateNamesFileName)); 

     int isPreferredName = 0; 
     int isShortName = 0; 
     int lines = 0; 

     System.out.println("Starting AlternateNames import..."); 

     while ((line = bReader.readLine()) != null) { 
      try { 
       String l[] = line.split("\t"); 
       if (l.length >= 4) { 
        BasicDBObject altName = new BasicDBObject(); 
        altName.put("alternateNameId", Integer.parseInt(l[0])); 
        altName.put("geonameId", Integer.parseInt(l[1])); 
        altName.put("isoLanguage", l[2]); 
        altName.put("alternateName", l[3]); 

        isPreferredName = 0; 
        isShortName = 0; 

        if (l.length == 5) { 
         isPreferredName = Integer.parseInt(l[4]); 
        } 

        if (l.length == 6) { 
         isPreferredName = Integer.parseInt(l[4]); 
         isShortName = Integer.parseInt(l[5]); 
        } 

        altName.put("isPreferredName", isPreferredName); 
        altName.put("isShortName", isShortName); 

        altNames.insert(altName); 

        lines++; 
       } 
      } catch (Exception ex) { 
      } 

     } 

     bReader.close(); 
     System.out.println("Number of lines parsed: " + lines); 

     System.out.println("Creating indexes..."); 
     altNames.createIndex(new BasicDBObject("geonameId", 1)); 
     altNames.createIndex(new BasicDBObject("isoLanguage", 1)); 
     altNames.createIndex(new BasicDBObject("alternateName", 1)); 

    } 
} 
2

你爲什麼不加入這樣

 String l[] = line.split("\t"); 
    if(l.length == 6) 
    { 
     BasicDBObject altName = new BasicDBObject(); 
     altName.put("alternateNameId", l[0]); 
     altName.put("geonameId", l[1]); 
     altName.put("isoLanguage", l[2]); 
     altName.put("alternateName", l[3]); 
      ... 
+0

Dur。我沒有想到這一點。這樣可行。但是,我現在從5.4M行到9500.大聲笑。如果我放棄最後兩個字段,它似乎也起作用。所以我想我需要考慮可變長度的字段。我會在每行中添加一些有條件的長度檢查。謝謝! – cbmeeks 2011-04-02 04:03:52

0

數組長度檢查,因爲我們還沒有表示你的例外是什麼行,我要用我的心理調試技能。

我的心理能力告訴我,你的文件末尾有一個空行,當你去尋找它的字段時,你會得到一個異常,因爲空行上沒有字段。

既可以查找空白行,也可以不嘗試查找不存在的字段。

+0

哈哈〜我也能感覺到你的心靈力量。 – RollingBoy 2011-04-02 04:01:51

+0

那麼,我是Java的新手,沒有看到提及的線路,而且很累。但是,謝謝你的機智的答案。 – cbmeeks 2011-04-02 04:04:51

1

本節

while ((line = bReader.readLine()) != null) { 
      String l[] = line.split("\t"); 
      BasicDBObject altName = new BasicDBObject(); 
      altName.put("alternateNameId", l[0]); 
      altName.put("geonameId", l[1]); 
      altName.put("isoLanguage", l[2]); 
      altName.put("alternateName", l[3]); 

是你所訪問的索引數組中的元素,但不是在一個的ArrayIndexOutOfBounds try/catch塊,其中只有部分,所以異常必須在這裏的某個地方拋出。因此,只要少於4個元素就可以在任何地方出現繁榮景象。在測試中捕捉整個事物,或者按照Bala的建議和測試l的長度來進行測試,然後再輸入代碼部分。

我想在任何需要從外部來源獲取數據的地方進行某種檢查,並且需要正確的內容才能正常工作。

+0

感謝您的信息。我想我比我想象的更累。大聲笑。這不是真正的生產代碼,只是一個小項目。我在下面發佈了我的固定示例(使用try/catch) – cbmeeks 2011-04-02 04:14:14

相關問題