NumberFormatException при анализе целого числа

У меня есть файл, который содержит множество названий фильмов, а также их годы, рейтинг из 5 звезд и продолжительность. Я пытаюсь прочитать файл и сохранить заголовки, год, рейтинг и длину в качестве переменных. Проблема, с которой я столкнулся, заключается в моем коде для получения года. Код компилируется, но затем при запуске генерирует исключение NumberFormatException, когда попадает в фильм с несколькими годами (например, он указан как 2006-2009). Вот мой код.

while((line = bufferedReader.readLine()) != null) {
                //System.out.println(line);
                for(int i = 0; i < line.length(); i++)
                {

                    if(line.charAt(i) == ')' || line.charAt(i) == '-')//get year
                    {
                        yr = line.substring(yearStart,i);
                        year = Integer.parseInt(yr);
                    }

                }
                System.out.println(year);

            }

Разве line.charAt(i) == '-' в моем выражении if не должно заботиться об этой проблеме?

РЕДАКТИРОВАТЬ: приведенный ниже код - это источник yearStart.

if(line.charAt(i) == '(')//get title
                    {
                        title = line.substring(0,i);
                        yearStart = i+1;
                    }

Файл имеет такой формат: title (year) | rating, length Извините, я должен был включить это изначально.

РЕДАКТИРОВАТЬ № 2: Вот образец части файла, если это поможет

!Women Art Revolution (2010) |   3 stars, 1hr 22m
#1 Cheerleader Camp (2010) |   3 stars, 1hr 35m
$5 a Day (2008) |   3.4 stars, 1hr 37m
'night, Mother (1986) |   3.7 stars, 1hr 36m
'Til Death (2006-2009) |   3.7 stars, 4 Seasons//This is the one that causes the error
@Suicide Room (2011) |   3.4 stars, 1hr 51m
... And God Spoke (1993) |   2.8 stars, 1hr 22m

person Austin Reynolds    schedule 09.11.2013    source источник
comment
Могу я предложить вам использовать отладчик и посмотреть, что произойдет?   -  person Alexis C.    schedule 10.11.2013
comment
Распечатайте строку, которую вы пытаетесь проанализировать, или посмотрите на трассировку стека исключений, чтобы увидеть, что на самом деле пытается проанализировать код. Это даст вам проблему и позволит вам найти решение. На самом деле, разместите здесь свою трассировку стека со своим вопросом, пожалуйста.   -  person Hovercraft Full Of Eels    schedule 10.11.2013
comment
Что такое yearStart?   -  person joval    schedule 10.11.2013
comment
Что такое yearStart? Здесь это важно, но я не вижу, чтобы он был определен или инициализирован. (джовал, сглаз!)   -  person kviiri    schedule 10.11.2013
comment
Используйте Eclipse и выясните, где именно возникает ошибка: eclipse. org/downloads/packages/eclipse-ide-java-developers/   -  person Duncan Calvert    schedule 10.11.2013
comment
@joval Извините, я отредактировал свой исходный пост, чтобы включить эту информацию.   -  person Austin Reynolds    schedule 10.11.2013
comment
@kviiri Я отредактировал исходный пост, чтобы включить эту информацию   -  person Austin Reynolds    schedule 10.11.2013
comment
Спасибо, Остин, посмотрю еще.   -  person kviiri    schedule 10.11.2013


Ответы (4)


Что происходит, когда вы нашли год? Цикл по-прежнему будет работать до конца строки, пытаясь анализировать вещи как числа каждый раз, когда он находит ) или -.

Возможно, вам следует выйти из цикла, как только вы найдете год.

                if(line.charAt(i) == ')' || line.charAt(i) == '-')//get year
                {
                    yr = line.substring(yearStart,i);
                    year = Integer.parseInt(yr);
                    break; // year found, no point in looping more
                }

Или, может быть, вам следует сбросить индекс yearStart, чтобы можно было проанализировать второй год.

                if (line.charAt(i) == '-')
                {
                    // parse first year
                    yr = line.substring(yearStart,i);
                    year = Integer.parseInt(yr);
                    yearStart = i + 1; // reset to parse second year
                }
                else if (line.charAt(i) == ')')
                {
                    yr = line.substring(yearStart,i);
                    year = Integer.parseInt(yr);
                    break; // year found
                }
person Joni    schedule 09.11.2013
comment
Ага! Это сделало это. Не могу поверить, что я не подумал об этом, лол. Большое спасибо, чувак - person Austin Reynolds; 10.11.2013

Поместите Intger.parseInt в блок try/catch (аналогичный приведенному ниже), чтобы увидеть, где это не удается и как:

try { 
  year = Integer.parseInt(yr);
} catch (Exception e) {
  throw new RuntimeException(
      "Failed to parse year '" + yr + "' in line '" + line + "'", e);
}

Кстати: line.indexOf(')') возвращает позицию '(' в строке.

person Stefan Haustein    schedule 09.11.2013
comment
Не удалось разобрать год "2006-2009" в строке "До смерти (2006-2009)" | 3,7 звезды, 4 сезона - person Austin Reynolds; 10.11.2013
comment
Похоже, именно то, что предложил другой ответ. Или вы проверяете неправильный символ («-» против «–»)? - person Stefan Haustein; 10.11.2013

После того, как первый год найден, yearStart все еще находится в индексе первого года. Поэтому, когда вы пытаетесь получить subString, это все еще (2006-2009) — автоматический NumberFormatException, не удается разобрать -.

Вы должны изменить yearStart после того, как будет найден первый год:

for(int i = 0; i < line.length(); i++)
{

    if(line.charAt(i) == ')' || line.charAt(i) == '-')//get year
    {
          yr = line.substring(yearStart,i);
          year = Integer.parseInt(yr);
          yearStart = i + 1;
    }

}
person Paul Samsotha    schedule 09.11.2013

Условие if(line.charAt(i) == ')' || line.charAt(i) == '-') выполняется дважды в вашем цикле. Сначала при совпадении дефиса, а затем при совпадении закрывающей скобки. В первый раз year назначается, в вашем примере, 2009. Но затем цикл продолжает работать, и через несколько итераций вы пытаетесь проанализировать "2005-2009", что приводит к исключению NumberFormatException.

Самое простое решение — break; выполнить цикл сразу после присвоения года, чтобы year присваивалось только один раз. Тем не менее, предположим, что вы хотите получить начальное значение интервала.

Более чистым решением было бы вообще избегать цикла и вместо этого разумно использовать String.indexOf. Что-то вроде этого (отказ от ответственности: не проверено).

String title;
int year;

while((line = bufferedReader.readLine()) != null) {

    title = line.substring(0, line.indexOf('('));

    int yearStart = line.indexOf('(') + 1;
    int yearEnd;
    if (line.indexOf('-', yearStart) > 0 ) {
        yearEnd = line.indexOf('-', yearStart);
    } else {
        yearEnd = line.indexOf('(', yearEnd);
    }

    int yr = line.substring(yearStart,i);
    year = Integer.parseInt(yr);

    System.out.println(year);
}

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

person ysmartin    schedule 09.11.2013
comment
Теперь я не уверен, правильно ли я понял ваш вопрос. Я предположил, что вы хотели получить 2005 год для фильма, чей год 2005-2009. Если вы хотите получить 2005, а затем 2009 год, мой код не будет применяться, хотя я все же рекомендую использовать indexOf - person ysmartin; 10.11.2013