Java 为什么我总是用这段代码获取ArrayIndexOutOfBoundsException?

Java 为什么我总是用这段代码获取ArrayIndexOutOfBoundsException?,java,exception,Java,Exception,我是一个Java新手,似乎不明白为什么这个粗糙的20分钟应用程序会抛出这个异常 基本上,我正在解析一个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.D

我是一个Java新手,似乎不明白为什么这个粗糙的20分钟应用程序会抛出这个异常

基本上,我正在解析一个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中的记录计数)时,它看起来很好……但我可能遗漏了什么

有什么建议吗

谢谢


顺便说一句,Java在不到3分钟的时间内解析了这个文本文件,真是太好了…

为什么不添加这样一个数组长度检查呢

     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]);
             ... 

为什么不添加这样的数组长度检查

     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]);
             ... 

既然你还没有指出你的异常在哪一行,我就用我的心理调试技巧

我的灵力告诉我,你的文件末尾有一个空行,当你去寻找其中的字段时,你会得到一个例外,因为空行上没有字段


要么寻找一个空行,要么不要试图寻找不存在的字段。

既然你还没有指出你的异常在哪一行,我将使用我的心理调试技能

我的灵力告诉我,你的文件末尾有一个空行,当你去寻找其中的字段时,你会得到一个例外,因为空行上没有字段

请查找空行,或者不要尝试查找不存在的字段。

本节

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个元素的线,它就会爆炸。在输入代码的这一部分之前,用try-catch或按照Bala的建议进行包装,并测试l的长度

我希望在几乎所有从外部源提取数据的地方进行某种检查,并且需要正确的内容才能正常工作

本节

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个元素的线,它就会爆炸。在输入代码的这一部分之前,用try-catch或按照Bala的建议进行包装,并测试l的长度


我希望在几乎所有从外部源提取数据的地方进行某种检查,并且需要正确的内容才能正常工作

这是我的正确代码。谢谢大家的提示

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));

    }
}

这是我的正确代码,它可以工作。谢谢大家的提示

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));

    }
}

你应该知道哪一行引发了异常,你可以通过查看行号然后检查代码来理解。你应该知道哪一行引发了异常,你可以通过查看行号然后检查代码来理解。哈哈~我也能感觉到你的精神力量。嗯,我是Java新手,没有看到线路在哪里被提到,而且很累。但是谢谢你机智的回答。哈哈~我也能感觉到你的灵力。嗯,我是爪哇的新手,不知道这句台词是在哪里提到的,而且很累。谢谢你机智的回答。我没想到。这很有效。然而,我现在从540万行增加到9500行。哈哈。如果我去掉最后两个字段,它似乎也能起作用。所以我想我需要考虑可变长度字段。我将在每行中加入一些条件长度检查。谢谢杜尔。我没想到。这很有效。然而,我现在从540万行增加到9500行。哈哈。如果我去掉最后两个字段,它似乎也能起作用。所以我想我需要考虑可变长度字段。我将在每行中加入一些条件长度检查。谢谢谢谢你的信息。我想我比我想象的要累。哈哈,这不是真正的生产代码,只是一个小项目。我在下面发布了我的固定示例(带有try/catch),感谢您提供的信息。我想我比我想象的要累。哈哈,这不是真正的生产代码,只是一个小项目。我在下面发布了我的固定示例(带有try/catch)