2015-09-07 2 views
-2

Я пишу фрагмент кода Java, который читает данные из TXT-файла и сохраняет его в 2D-массиве. Для некоторых файлов код работает отлично, но для других файлов он генерирует исключение ArrayIndexOutOfBoundsException, хотя, насколько я могу судить, массив имеет достаточно места!Array Index за пределами границ, хотя достаточно свободного места

Вот код:

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

public class ExtractData { 
    static String[][] data; 
    static String line; 
    static int amountOfEntries; 
    static int amountOfSeparators; 

    public static String[][] getData(String filename) throws IOException { 
     BufferedReader in = new BufferedReader(new FileReader(filename)); 
     System.out.println("Fetching data for file " + filename); 
     amountOfEntries = Utilities.countLines(filename); 
     amountOfSeparators = (Utilities.countOccurencesOfCharacter(filename, ' ')/amountOfEntries) + 1; 

     String[] temp = new String[amountOfEntries]; // for extracted data, still needs to be separated 
     int alpha = 0; 
     while((line = in.readLine()) != null) { 
      temp[alpha] = line; 
      alpha++; 
     } 
     in.close(); 
     System.out.println("Done!"); 

     System.out.println("Parsing Data to Cache..."); 
     String[][] parsedData = new String[amountOfEntries][amountOfSeparators]; 

     String[] parts = new String[amountOfSeparators]; 
     for (int i = 0; i < amountOfEntries; i++) { 
      parts = (temp[i]).split(" "); 
      for (int k = 0; k < amountOfSeparators; k++) { 
       parsedData[i][k] = parts[k]; 
       Utilities.debugMethod(filename + "[" + i + "][" + k + "]", parsedData[i][k]); 
      } 
     } 
     System.out.println("Done!"); 
     return parsedData; 
    } 

    public static void fetchDataAndParsetoSQL(String filename) throws IOException { 
     System.out.println("Present working directory: " + System.getProperty("user.dir")); 
     data = getData(filename); 
     System.out.println("Creating SQL statements and writing to file..."); 
     String tablename = Utilities.sqltableName(filename); 
     toSQL.SQLOutput(data, tablename, filename); 
     System.out.println("Done!"); 
    } 
} 

я получаю исключение на линии

parsedData[i][k] = parts[k]; 

Это очень раздражает, и я не могу найти ответ на проблемы в любом месте, особенно так как даже с текстовыми файлами, на которых он не работает, он все еще правильно разбирает первые 60 строк файла, прежде чем бросать исключение.

У кого-нибудь есть идея, что может вызвать это?

+0

Просьба показать точное исключение вместе со значениями 'i' и' k'. Обратите внимание, что код, который вы представили, даже не компилируется, так как '' '' не является допустимым символьным литералом. –

+0

Не должно ли условие цикла учитывать детали []? – dly

+0

Исключение указывает размер массива и используемое значение индекса. Один из них - это не то, что вы ожидаете. И * всегда * указывайте сообщение об ошибке * whole * и * exact *, когда вы жалуетесь на ошибку. –

ответ

0
parts = (temp[i]).split(" "); 

Эта строка возвращает новый массив, который затем хранится в переменной parts. Выбранный вами массив больше не ссылается на parts.

Этот новый массив, созданный split(), будет содержать столько элементов, сколько элементов между разделителями. Не гарантируется наличие точно amountOfSeparators элементов или более. Ваше объявление внутренний цикл должен быть:

for(int k = 0; k < amountOfSeparators && k < parts.size(); k++) { 

(также примечание по стилю: использовать согласованные пробелы вокруг операторов, например k < amountOfSeparators не k< amountOfSeparators, а также использовать более описательные итераторы чем i, k, так как в этом случае у них есть значение, отличное от наивных итераторов, и у вас есть ряд из них - лучшие имена могут значительно облегчить выполнение сложных циклов.)

+0

Спасибо, что это исправлено! –

2

Вы полагаете, что parts массива всегда будет иметь amountOfSeparators элементов, но каждый раз, когда вы присваиваете ему новый массив, вызвав parts = (temp[i]).split(" ");, и некоторые из этих вызовов, вероятно, возвращают короткий массив, чем вы ожидаете.

Следующий код будет убедиться, что parts массив имеет требуемую длину:

parts = (temp[i]).split(" "); 
parts = Arrays.copyOf(parts, amountOfSeparators); 
+0

Да! Это именно то, что происходит, просто распечатайте длину деталей для каждого рекурсивного вызова. Однако, когда (temp [i]). Split (""); имеет f.i. 74 записи и части 77, как я могу установить оставшиеся неиспользуемые индексы, допустим, null? Я думал, что это будет автоматически ... –

+0

@SpadeJohnsson Вы можете создать новый массив элементов 'amountOfSeparators' на каждой итерации, а затем скопировать в него элементы массива' (temp [i]). Split ("") , Таким образом, неиспользованные индексы будут нулевыми. – Eran

+0

@SpadeJohnsson Или лучше - 'parts = (temp [i]). Split (" "); parts = Arrays.copyOf (parts, amountOfSeparators); ' – Eran

Смежные вопросы