2014-01-20 12 views
-1

我寫了一些採用格式爲「1 day hh:mm:ss」的字符串的代碼。使用字符串標記器,我試圖將字符串分成不同的關注部分,即將1天轉換爲86400秒,將小時轉換爲分鐘等等。我遇到了秒數錯誤,並用我的代碼返回。我無法弄清楚問題出在哪裏。我在週末考慮了這個問題,作爲最後的決定,我決定向更廣泛的社區徵求更正的幫助,並提出更好的改進這些代碼的建議。Java中的最終字符串Tokenizer錯誤

目標:讀入格式爲「X days 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)" 

我收集它是與無法解析最終詮釋(「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 at ReadIn.main(ReadIn.java:60) - ReadIn.parseTime(ReadIn.java:110) (ReadIn.java:60) - 剛編輯過的爲清晰起見。 –

+1

沒有下一個標記,你對異常有什麼不瞭解? – 2014-01-20 20:25:13

回答

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是保留兼容性的原因,雖然它的使用是在新代碼氣餒的遺留類。建議任何尋求此功能的人使用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查看最終編輯 –

+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); 
}