Очень странное исключение StringIndexOutOfBoundsException

Прежде чем задать этот вопрос, я потратил около получаса в Google, но, поскольку я не нашел решения, я подумал, что мне, возможно, стоит спросить здесь. Итак, в основном я использую Java Reader для чтения текстового файла и преобразования каждой строки информации в объект, который я назвал Nation (конечно, с конструктором), и создания массива из всех этих объектов. Проблема в том, что одна строка в моем текстовом файле состоит из 75 символов. Но я получаю сообщение об ошибке, что длина всего 68! Итак, вот часть кода, в которой я читаю информацию из файла:

static int lireRemplir (String nomFichier, Nation[] nations)
    throws IOException
{
    boolean existeFichier = true;
    int n =0;

    FileReader fr = null;

    try {
        fr = new FileReader(nomFichier);
    }
    catch (java.io.FileNotFoundException erreur) {
        System.out.println("Probléme avec l'ouverture du fichier " + nomFichier);
        existeFichier = false;
    }

    if (existeFichier) {

        BufferedReader entree = new BufferedReader(fr);
        boolean finFichier = false;

        while (!finFichier) {

            String uneLigne = entree.readLine();

            if (uneLigne == null) {
                finFichier=true;
            }
            else {

                nations[n] = new Nation(uneLigne.charAt(0),uneLigne.substring(55,63),
                       uneLigne.substring(64,74),uneLigne.substring(1,15),uneLigne.substring(36,54));

                n++;
            }
        }

        entree.close();
    }

    return n;
}

Я получаю следующую ошибку:

Exception in thread "main" java.lang.StringIndexOutOfBoundsException: begin 64, end 74, length 68

Поскольку я здесь новичок, я попытался опубликовать изображение своего текста, но не смог, поэтому я просто попробую вручную написать пример:

2ETATS-UNIS WASHINGTON 9629047 291289535

4ЧИНЕ ПЕКИН 9596960 1273111290

3JAPON KYOTO 377835 12761000

Между словами много места, это как массив!

Если я изменю 74 на 68, я получаю результат, когда пытаюсь распечатать свой массив, но информация отсутствует.

Вот мой конструктор:

public Nation(char codeContinent, String superficie, String population, String nom, String capitale) {
    this.codeContinent = codeContinent;
    this.superficie = superficie;
    this.population = population;
    this.nom = nom;
    this.capitale = capitale;
}

Надеюсь, вы могли бы мне помочь с этим! Если вам нужно узнать больше о моем коде, дайте мне знать! Большое спасибо.

The problem is that a single line on my text file goes to 75 characters - возможно, это не так для всех строк вашего файла. Достаточно легко проверить, есть ли более короткие строки. Просто выведите длину каждой строки.
Eran 30.05.2018 12:30

Как уже упоминалось, просто добавьте System.out.println(uneLigne.length()) в качестве первого оператора блока else.

user7 30.05.2018 12:33

Не заслуживает доверия. java.lang.String.substring() достаточно хорошо протестирован за последние 22 года. Очевидно, вы ошибаетесь насчет длины строки. Если вы не согласны, предоставьте убедительные доказательства.

user207421 30.05.2018 12:33

Где-то в вашем файле есть строка всего из 68 символов. Посчитай еще раз. И убедитесь, что при подсчете вы используете кодировку символов по умолчанию для вашей платформы.

Dawood ibn Kareem 30.05.2018 12:36

Я попытался распечатать длину каждой строки, и выяснилось, что есть только одна строка с 68 символами, все остальные - 71,72 или 73

Django 30.05.2018 12:36

Да. Точно. Вы получите ошибку в строке из 68 символов.

Dawood ibn Kareem 30.05.2018 12:37

Вы не предоставили примеры данных, из которых извлекаете подстроку. Обязательно ли использовать подстроку? Может быть, можно извлечь нужные данные, используя комбинацию contains() и indexOf() или даже regExp, независимо от длины строки?

hamena314 30.05.2018 12:44

Данные, которые я извлекаю, выглядят так: 2ETATS-UNIS WASHINGTON 9629047 291289535 это массив, поэтому между словами много места, есть ли у вас какие-либо другие предложения, я буквально новичок в java

Django 30.05.2018 12:51

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

hamena314 30.05.2018 12:52

Пожалуйста, опубликуйте дословный пример кода, который вы хотите обработать. Вы написали "между словами много пробела", сколько пробелов? Как заполнено пространство? Добавьте примеры в виде блоков кода, чтобы не терять пробелы при форматировании.

hamena314 05.06.2018 09:24
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
10
90
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Чтобы избежать исключений времени выполнения, вам нужно быть осторожным с вашим кодом. В случаях, когда вы имеете дело с индексами String или массива, убедитесь, что длина String больше или равна максимальному индексу, который вы используете. Приложите код, который генерирует исключение, в:

    if (uneLigne.length() > 74) {
        nations[n] = new Nation(uneLigne.charAt(0),uneLigne.substring(55,63),
                       uneLigne.substring(64,74),uneLigne.substring(1,15),uneLigne.substring(36,54));
    } else {
       //your logic to handle the line with less than 74 characters
    }

Это гарантирует, что ваш код не сломается, даже если какая-либо строка меньше ожидаемых символов.

______________________________________________________________________________

Другой подход

Добавление комментария в качестве ответа:

Другой способ - использовать метод расколоть() класса String или StringTokenizer для получения массива / токенов, если строка разделена пробелом или каким-либо другим символом. При этом вам не нужно разбивать строку с помощью метода substring (), когда вам нужно беспокоиться о длине и возможном времени выполнения.

Проверьте приведенный ниже фрагмент кода, используя метод split (), для каждой строки, которую вы читаете из файла, вам, вероятно, придется делать это следующим образом:

Nation nation = null;
String uneLigne = "2ETATS-UNIS WASHINGTON 9629047 291289535";
String[] strArray = uneLigne.split(" ");
if (strArray.length > 3) {
    nation = new Nation(getContinentCodeFromFirstElement(strArray[0]), strArray[1], 
        strArray[2], strArray[3], strArray[4]);
}

//getContinentCodeFromFirstElement(strArray[0]) is your private method to pick the code from your first token/element.

Я понимаю ! Но разве нет другого решения, кроме как обрабатывать его по длине?

Django 30.05.2018 12:49

@Django: См. Мой комментарий к самому вопросу: вы должны предоставить примеры данных, которые вы используете. Может быть, есть способ сделать то, что вы хотите, без использования жестко запрограммированных чисел. Это решение также не собирает информацию в строках с length < 74 ... может быть, это не нужно?

hamena314 30.05.2018 12:51

Другой способ - использовать метод split () класса String или StringTokenizer для получения токенов, если строка разделена пробелом или каким-либо другим символом. При этом вам не нужно разбивать строку с помощью метода substring ().

JavaYouth 30.05.2018 12:53

Я только что выложил пример своих данных!

Django 30.05.2018 13:00

Для каждой строки вам, вероятно, придется сделать так: String str= "2ETATS-UNIS WASHINGTON 9629047 291289535"; String[] strArray = str.split(" "); if (strArray.length > 3) { Nation nation = new Nation(getCodeFromFirstElement(strArray[0]), strArray[1], strArray[2], strArray[3], strArray[4]) }

JavaYouth 30.05.2018 13:11

Хорошо ! Большое спасибо, Хамена, за ваш конкретный пример, мне пришлось написать дополнительную строку кода, но теперь он работает! Поскольку никто не голосует против этого вопроса, я просто буду придерживаться вашего ответа!

Django 30.05.2018 13:12

Спасибо вам тоже JavaYouth!

Django 30.05.2018 13:14

@Django: Я не ответил на ваш вопрос, но JavaYouth ответила. Если он вставит код из своего комментария в свой ответ, я с радостью проголосую за него.

hamena314 30.05.2018 13:35

Добавлен код из комментария для ответа в качестве альтернативного подхода

JavaYouth 31.05.2018 05:21
Ответ принят как подходящий

Самый простой способ решить вашу проблему - заменить 74 на une Ligne.length. Вот новый код.

nations[n] = new Nation(uneLigne.charAt(0),uneLigne.substring(55,63),
                       uneLigne.substring(64,uneLigne.length),uneLigne.substring(1,15),uneLigne.substring(36,54));

Это будет работать, если ваша строка гарантированно содержит> 64 символа, в противном случае вы получите то же исключение.

JavaYouth 31.05.2018 05:16

Из того, что он опубликовал, я понял, что текстовый файл похож на массив, поэтому всегда есть номер строки, с которой начинается столбец, и это 64 для его случая.

Ahmed Bendaya 04.06.2018 20:45

Он сказал, что «между словами много пробела», но не уточнил, сколько места. Таким образом, могут быть примеры, содержащие менее 64 символов, которые не будут работать с этим решением.

hamena314 05.06.2018 09:25

Ахмед прав, он всегда начинается с определенного номера строки, поэтому он решил мою проблему без особых изменений в моем коде! спасибо за ваши ответы всем вам

Django 05.06.2018 17:56

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