2014-01-20 5 views
-1

Я написал код, который принимает строку формата «1 день hh: mm: ss». Используя строковый токенизатор, я пытаюсь разделить строку на различные интересующие нас разделы, а именно конвертировать 1 день в 86400 секунд, часы в минуты и т. Д. У меня ошибка, достигающая секунд, и возвращаю ее с моим кодом. Я не могу понять, где проблема. Я подумал об этом в выходные, и в крайнем случае я решил обратиться к более широкому сообществу за помощью по исправлению ситуации и предложениям улучшить этот код.Ошибка финального скрипта String в Java

Цель: прочитать в строке формата «X дней hh: mm: ss» и преобразовать это в секунды. Код прилагается ниже.

Эта ошибка я получаю следующим образом:

"java.util.NoSuchElementException 
at java.util.StringTokenizer.nextToken(StringTokenizer.java:332) 
at ReadIn.parseTime(ReadIn.java:110) 
at ReadIn.main(ReadIn.java:60)" 

Я собрал у него есть что-то делать с не в состоянии разобрать окончательный Int («SS») значения format.I'm не почему это так, и хотел бы, чтобы ясность была в том, что я делаю неправильно.

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

Заранее благодарен!

public static int parseTime(String s) { 

    int days = 0; 
    int hours = 0; 
    int minutes = 0; 
    int seconds = 0; 

    try{ 


    StringTokenizer st = new StringTokenizer(s,": "); 
    if(s.contains("day")){ 

      days = Integer.parseInt(st.nextToken()); 
      String throwAway = st.nextToken();// day 
      throwAway = throwAway.substring(0, throwAway.lastIndexOf(throwAway)); 
      hours = Integer.parseInt(st.nextToken()); 
      throwAway = st.nextToken();//hours 
      throwAway = throwAway.substring(0, throwAway.lastIndexOf(throwAway)); 
      minutes = Integer.parseInt(st.nextToken()); 
      throwAway = throwAway.substring(0, throwAway.lastIndexOf(throwAway)); 
      seconds = Integer.parseInt(st.nextToken()); 
      throwAway = st.nextToken(); 

     } 

    }catch(NoSuchElementException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    }catch(NumberFormatException e){ 
     e.printStackTrace(); 
    } 

    return (days*86400 + hours*3600 + minutes*60 + seconds*1); 

} 
+0

У тебя ошибка ...? Какая ошибка? – Bart

+0

java.util.NoSuchElementException в java.util.StringTokenizer.nextToken (StringTokenizer.java:332) в ReadIn.parseTime (ReadIn.java:110) в ReadIn.main (ReadIn.java:60) - Просто редактировал сообщение для ясности. –

+1

нет следующего токена, что вы не понимаете об исключении? –

ответ

2

По моим подсчетам ваша строка будет производить 5 жетонов. Вы звоните nextToken() 6 раз. И в шестой раз это будет исключение.

X days hh:mm:ss 
1 2 3 4 5 

Стоит также отметить, что все, что вы пытаетесь сделать с этими вызовами substring() ... не делать то, что вы думаете. Они ничего не делают, и вы можете их удалить.

В конце концов, все, что вам нужно:

days = Integer.parseInt(st.nextToken()); // token 1 
st.nextToken();// // token 2 ("days") 
hours = Integer.parseInt(st.nextToken()); // token 3 
minutes = Integer.parseInt(st.nextToken()); // token 4 
seconds = Integer.parseInt(st.nextToken()); // token 5 

переменная throwaway не требуется; просто не назначая возвращаемое значение из звонка на nextToken(), он собирается ... выбросить его.

Все, что сказал, есть другие способы решения этой проблемы. В самом деле, Javadocs for StringTokenizer гласит:

StringTokenizer является наследием класс, который сохраняется в целях совместимости, хотя его использование не рекомендуется в новом коде. Рекомендуется, чтобы любой, кто ищет эту функциональность, использовал метод split для String или пакет java.util.regex.

с помощью регулярных выражений и захвата групп, например, будет выглядеть следующим образом:

final Pattern pattern = Pattern.compile("(\\d+) days (\\d\\d):(\\d\\d):(\\d\\d)"); 
final Matcher matcher = pattern.matcher(yourString); 
if (matcher.find()) 
{ 
    days = Integer.parseInt(matcher.group(1)); 
    hours = Integer.parseInt(matcher.group(2));  
    minutes = Integer.parseInt(matcher.group(3)); 
    seconds = Integer.parseInt(matcher.group(4)); 
} 
+0

Спасибо! Это конструктивное понимание. –

+0

@ k..a..b see final edit –

+0

Я кое-что узнал сегодня. Полностью понять основную причину ошибки. Благодаря! –

1

Существует способ сделать расчет только в одной строке:

public static int parseTime(String s) { 
    try { 
     return (int) ((new SimpleDateFormat("yyyy-MM-dd 'days' hh:mm:ss").parse("1970-01-" + s).getTime() - new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").parse("1970-01-01 00:00:00").getTime())/1000); 
    } catch (ParseException e) { 
     throw new IllegalArgumentException(); 
    } 
} 

Это работает, потому что (невероятно) SimpleDateFormat позволяет более дней, чем на самом деле в месяц - это просто зашкаливает к следующему месяц, например, «1970-01-32» анализируется как «1970-02-01», и нет ограничений на количество дней, с которыми оно будет работать.

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

+0

Спасибо! Я хотел лучше понять, что я делаю неправильно, но это тоже помогает. –

1

Рассмотрим упрощая синтаксического анализа логики:

public static int parseTime(String s) { 
    int days = 0; 
    int hours = 0; 
    int minutes = 0; 
    int seconds = 0; 

    try{ 
     s = s.replaceFirst("\\s+days?\\s+", ":"); 
     StringTokenizer st = new StringTokenizer(s, ":"); 
     days = Integer.parseInt(st.nextToken()); 
     hours = Integer.parseInt(st.nextToken()); 
     minutes = Integer.parseInt(st.nextToken()); 
     seconds = Integer.parseInt(st.nextToken()); 

    } catch(NoSuchElementException | NumberFormatException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

    return (days*86400 + hours*3600 + minutes*60 + seconds); 
} 
Смежные вопросы