ArrayIndexOutOfBoundsException внутри жестко заданных границ

Работаю над заданием, где я должен читать данные из файла в массив, чтобы выполнить некоторые демонстрации поиска/сортировки.

public class A5 {
public static void main(String[] args) throws FileNotFoundException, IOException {
     fileToArray();
}
 /**
 * populates array from file
 * @throws IOException
 * @throws FileNotFoundException
 */
public static <T extends Comparable<T>> void fileToArray() throws IOException, FileNotFoundException {
    int FileIndex = 0;

    A5GItem[] gItems = new A5GItem[5150];
        File file = new File("GroceryData.txt");
        Scanner inputFile = new Scanner(file);


        while (inputFile.hasNext()) {
                String line = inputFile.nextLine().replace(" oz", "").replace("«", "");

            String[] tokens = line.split(";");
            if (tokens.length == 5) {

            System.out.println(tokens[0]);
            System.out.println(tokens[1]);
            System.out.println(tokens[2]);
            System.out.println(tokens[3]);
            System.out.println(tokens[4]);
            System.out.println(FileIndex);

            FileIndex++;
            else {
                System.out.println("Bad line: " + line);} 
                        }   }`

Я попытался проверить, правильно ли я заполнил массив, зациклив некоторые операторы println. Он правильно токенизирует первые 400 (примерно) элементов в списке, а затем печатает только половину последнего токена и выдает

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 2 at A5.fileToArray(A5.java:59) at A5.main(A5.java:16)

после того, как пробежался с этим индексом для многих итераций. Не знаю, с чего начать устранение неполадок.

tokens = line.split(";");: это не кажется запрограммированным...
ernest_k 21.03.2019 06:28

Я предполагал, что строка над ней устанавливает границы, учитывая, что никогда не бывает более 5 токенов.

M. Henny 21.03.2019 06:30

Позаботьтесь о соглашении об именах Java. Имена переменных должны начинаться с символов нижнего регистра.

Jens 21.03.2019 06:33

Напечатайте line напрямую, это должно стать хорошим началом для устранения этой проблемы.

Joakim Danielson 21.03.2019 06:38

Для чего вы используете FileIndex? Поскольку вы используете сканер, hasNext выполняется построчно. И, как написал @Jens: нотация в верблюжьем регистре. Нет переменных, начинающихся с верхнего регистра. А что такое строка 59 в вашем случае?

Alexander Falk 21.03.2019 06:39

@AlexanderFalk Я использовал эту переменную для некоторых более поздних шагов, я не заполнил общий массив токенами.

M. Henny 21.03.2019 06:41

Инициализация токенов в tokens = new String[5]; является избыточной и не гарантирует, что ваш массив токенов будет состоять из пяти элементов. Скорее вы должны написать if (tokens.length == 5) { do your stuff } else { System.out.println("Bad line: " + line)}

Pushpesh Kumar Rajwanshi 21.03.2019 06:41

@PushpeshKumarRajwanshi Обновлено. Я до сих пор не могу найти, что отделяло эту строку файла от следующей. Речь идет о строке Beech-Nut Stage 2;Mixed Vegetables;4 oz;5.67;6047, где последний токен заканчивается на Vegeta. Список перед этим выглядит как Beech-Nut Stage 2;Pears & Pineapple;4 oz;7.27;6031 Beech-Nut Stage 2;Pears & Raspberries;4 oz;8.83;5731 Beech-Nut Stage 2;Butternut Squash;4 oz;1.39;5932 Beech-Nut Stage 2;Corn & Sweet Potatoes;4 oz;5.12;5796 Beech-Nut Stage 2;Country Garden Vegetables;4 oz;10.04;6046 для сравнения

M. Henny 21.03.2019 06:48
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
3
8
48
1

Ответы 1

Очевидно, что одна из строк в файле "GroceryData.txt" не содержит 5 токенов. Обратите внимание, что метод split() возвращает массив, размер которого не может быть равен 5. Поэтому инициализация переменной tokens не требуется. Кажется, что переменная FileIndex подсчитывает прочитанные строки, поэтому я предлагаю распечатать ее, а также напечатать размер массива tokens после split(), например.

while (inputFile.hasNext()) {
    String line = inputFile.nextLine().replace(" oz", "").replace("«", "");
    String[] tokens = line.split(";");
    FileIndex++;
    System.out.println("Line: " + FileIndex + " has " + tokens.length + " tokens.");
}

Затем вы обнаружите, какая строка файла не соответствует вашим ожиданиям.

Кстати, что касается соглашения об именах, которое упоминают комментаторы, это просто соглашение. Это не то, что вызывает ваш ArrayIndexOutOfBoundsException

Также опубликованная вами трассировка стека указывает на то, что строка 59 вашего кода содержит проблему. Я думаю, что это была бы эта линия...

System.out.println(tokens[2]);

Печать элементов массива предполагает, что он содержит 5 элементов, но, как я и другие упоминали, метод split() может не возвращать массив из 5 элементов.

Сначала попробуйте то, что я предложил. Вам нужно отладить свой код, а не просто пройтись по нему. Я предложил простой способ определить, что может быть причиной Exception.

Abra 21.03.2019 06:58

Поиск строки, вызывающей исключение, не был проблемой, я разместил ее в комментарии выше. Строка была Beech-Nut Stage 2;Mixed Vegetables;4 oz;5.67;6047, и я не вижу, чем она отличается от предыдущих строк Beech-Nut Stage 2;Pears;4 oz;2.95;5925 Beech-Nut Stage 2;Pears & Pineapple;4 oz;7.27;6031 Beech-Nut Stage 2;Pears & Raspberries;4 oz;8.83;5731 Beech-Nut Stage 2;Butternut Squash;4 oz;1.39;5932 Beech-Nut Stage 2;Country Garden Vegetables;4 oz;10.04;6046. Последний токен заканчивается тем, что Vegata уже несколько раз без проблем разделил строковые овощи.

M. Henny 21.03.2019 07:00

Вы нашли плохую линию, но знаете ли вы, почему она плохая? Очевидно, он не содержит 5 токенов. Вы знаете, сколько жетонов split() вернулось за эту строку? Кроме того, какая строка исходного кода, которую вы разместили, является строкой 59?

Abra 21.03.2019 07:05

2 Beech-Nut Stage 2 и Mixed Vegeta. Строка 59 была бы System.out.println(tokens[2]);

M. Henny 21.03.2019 07:07

Это не похоже на код Java. Я имел в виду строку 59 вашего java-кода. Если вы используете IDE, например Затмение, в трассировке стека должна быть ссылка, которая приведет вас прямо к этой строке в вашем коде.

Abra 21.03.2019 07:10

Выложил первую половину ответа перед строкой кода. Этот бит был из файла. Трудно превзойти ввод мышечной памяти в комментариях на этом сайте.

M. Henny 21.03.2019 07:11

удалив строку Beech-Nut Stage 2;Mixed Vegetables;4 oz;5.67;6047, и код заработал без ошибок. Я просто не могу понять, чем отличается эта строка

M. Henny 21.03.2019 07:17

Именно то, что я подозревал. ArrayIndexOutOfBoundsException потому что tokens содержит только два элемента. Вам нужно тщательно изучить эту линию. Возможно, распечатайте символы, используя метод toCharArray() класса java.lang.String.

Abra 21.03.2019 07:19

Когда я вырезал и вставил строку обратно в файл после ее удаления, эта строка теперь работает правильно. Я предполагаю, что профессор включил какой-то специальный символ в качестве пограничного случая, который был удален при копировании.

M. Henny 21.03.2019 07:22

Другие вопросы по теме