2017-06-01 100 views
0

我有一個文件可以讀取,並且使用這段代碼,我成功地完成了我的JUnit測試。如您所見,我將String行作爲參數傳遞給readPrevisione(...)方法。字符串行或StringTokenizer與讀者?

package oroscopo.persistence; 

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.Reader; 
import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.HashSet; 
import java.util.List; 
import java.util.NoSuchElementException; 
import java.util.Set; 
import java.util.StringTokenizer; 

import oroscopo.model.Previsione; 
import oroscopo.model.SegnoZodiacale; 

public class TextFileOroscopoRepository implements OroscopoRepository { 

private HashMap<String, List<Previsione>> mapSettore = new HashMap<>(); 


public TextFileOroscopoRepository(Reader baseReader) throws IOException, BadFileFormatException{ 
    if (baseReader == null) 
     throw new IllegalArgumentException("baseReader is null"); 
    BufferedReader bufReader = new BufferedReader(baseReader); 
    String line; 
    while((line=bufReader.readLine()) != null){ 
     readPrevisione(line,bufReader); 
    } 



} 

private void readPrevisione(String line, BufferedReader bufReader) throws IOException, BadFileFormatException{ 
    String nomeSettore = line.trim(); 
    if (!Character.isUpperCase(nomeSettore.charAt(0))) 
     throw new BadFileFormatException(); 
    List<Previsione> listaPrev = new ArrayList<>(); 
    while (!(line = bufReader.readLine()).equalsIgnoreCase("FINE")){ 
     try{ 
     StringTokenizer st1 = new StringTokenizer(line, "\t"); 
     if(st1.countTokens() < 2) 
      throw new BadFileFormatException(); 
     String prev = st1.nextToken("\t").trim(); 
     int val = Integer.parseInt(st1.nextToken("\t").trim()); 
     Set<SegnoZodiacale> segni = new HashSet<>(); 
     if (st1.hasMoreTokens()){ 
      while(st1.hasMoreTokens()){ 
       try{ 
       segni.add(SegnoZodiacale.valueOf(st1.nextToken(",").trim())); 
       } 
       catch (IllegalArgumentException e){ 
       throw new BadFileFormatException(); 
       } 
      } 
      Previsione p = new Previsione(prev,val,segni); 
      listaPrev.add(p); 
     } 
     else{ 
      Previsione p2 = new Previsione(prev,val); 
      listaPrev.add(p2); 
     } 
     } 
     catch (NumberFormatException e){ 
      throw new BadFileFormatException(); 
     } 
     catch (NoSuchElementException e){ 
      throw new BadFileFormatException(); 
     } 

    } 
    mapSettore.put(nomeSettore, listaPrev); 
} 

@Override 
public Set<String> getSettori() { 
    return mapSettore.keySet(); 
} 

@Override 
public List<Previsione> getPrevisioni(String settore) { 
    return mapSettore.get(settore.toUpperCase()); 
    } 
} 

這裏有相同的代碼,而不是通過讀線爲參數,我通過已經讀了線的StringTokenizer。它應該像上面那樣工作,但是我的JUnit測試失敗了。我做錯了什麼?

package oroscopo.persistence; 

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.Reader; 
import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.HashSet; 
import java.util.List; 
import java.util.NoSuchElementException; 
import java.util.Set; 
import java.util.StringTokenizer; 

import oroscopo.model.Previsione; 
import oroscopo.model.SegnoZodiacale; 

public class TextFileOroscopoRepository implements OroscopoRepository { 

private HashMap<String, List<Previsione>> mapSettore = new HashMap<>(); 


public TextFileOroscopoRepository(Reader baseReader) throws IOException, BadFileFormatException{ 
    if (baseReader == null) 
     throw new IllegalArgumentException("baseReader is null"); 
    BufferedReader bufReader = new BufferedReader(baseReader); 
    String line; 
    while((line=bufReader.readLine()) != null){ 
     StringTokenizer st = new StringTokenizer(line); 
     readPrevisione(st,bufReader); 
    } 



} 

private void readPrevisione(StringTokenizer st, BufferedReader bufReader) throws IOException, BadFileFormatException{ 
    String nomeSettore = st.nextToken().trim(); 
    if (!Character.isUpperCase(nomeSettore.charAt(0))) 
     throw new BadFileFormatException(); 
    List<Previsione> listaPrev = new ArrayList<>(); 
    String line; 
    while (!(line = bufReader.readLine()).equalsIgnoreCase("FINE")){ 
     try{ 
     StringTokenizer st1 = new StringTokenizer(line, "\t"); 
     if(st1.countTokens() < 2) 
      throw new BadFileFormatException(); 
     String prev = st1.nextToken("\t").trim(); 
     int val = Integer.parseInt(st1.nextToken("\t").trim()); 
     Set<SegnoZodiacale> segni = new HashSet<>(); 
     if (st1.hasMoreTokens()){ 
      while(st1.hasMoreTokens()){ 
       try{ 
       segni.add(SegnoZodiacale.valueOf(st1.nextToken(",").trim())); 
       } 
       catch (IllegalArgumentException e){ 
       throw new BadFileFormatException(); 
       } 
      } 
      Previsione p = new Previsione(prev,val,segni); 
      listaPrev.add(p); 
     } 
     else{ 
      Previsione p2 = new Previsione(prev,val); 
      listaPrev.add(p2); 
     } 
     } 
     catch (NumberFormatException e){ 
      throw new BadFileFormatException(); 
     } 
     catch (NoSuchElementException e){ 
      throw new BadFileFormatException(); 
     } 

    } 
    mapSettore.put(nomeSettore, listaPrev); 
} 

@Override 
public Set<String> getSettori() { 
    return mapSettore.keySet(); 
} 

@Override 
public List<Previsione> getPrevisioni(String settore) { 
    return mapSettore.get(settore.toUpperCase()); 
    } 

} 

編輯:這是我想讀File.txt

這裏是我的JUnit測試的一個示例:

@Test 
public void testLetturaCorrettaPrevisioni1() throws IOException, BadFileFormatException { 
    Reader mr = new StringReader(
      "NOMESEZIONE\navrai la testa un po' altrove\t\t4\tARIETE,TORO,GEMELLI\ngrande intimita'\t9\nFINE\n" 
        + "SEZIONE2\ntesto di prova\t\t\t\t\t66\t\nFINE"); 

    OroscopoRepository or = new TextFileOroscopoRepository(mr); 

    assertEquals("avrai la testa un po' altrove", or.getPrevisioni("nomesezione").get(0).getPrevisione()); 
    assertEquals(4, or.getPrevisioni("nomesezione").get(0).getValore()); 
    Set<SegnoZodiacale> validi = new HashSet<SegnoZodiacale>() { 
     private static final long serialVersionUID = 1L; 

     { 
      add(SegnoZodiacale.ARIETE); 
      add(SegnoZodiacale.TORO); 
      add(SegnoZodiacale.GEMELLI); 
     } 
    }; 
    for (SegnoZodiacale s : SegnoZodiacale.values()) { 
     if (validi.contains(s)) 
      assertTrue(or.getPrevisioni("nomesezione").get(0).validaPerSegno(s)); 
     else 
      assertFalse(or.getPrevisioni("nomesezione").get(0).validaPerSegno(s)); 
    } 

    assertEquals("grande intimita'", or.getPrevisioni("nomesezione").get(1).getPrevisione()); 
    assertEquals(9, or.getPrevisioni("nomesezione").get(1).getValore()); 
    for (SegnoZodiacale s : SegnoZodiacale.values()) { 
     assertTrue(or.getPrevisioni("nomesezione").get(1).validaPerSegno(s)); 
    } 
} 
+0

如果'readLine()'返回一個意外的null,那麼兩個版本都包含潛在的NPE。 – EJP

+0

如果readLine()返回null,則表示file.txt爲空。在程序的Controller部分(此處未顯示)中,如果HashMap爲空,則會引發異常..但無論如何,這不是重點。問題出在StringTokenizer和作爲參數傳遞的String之間。 – FollettoInvecchiatoJr

+0

這意味着該文件是空的*或*不包含「FINE」行。我發表評論,而不是答案。 – EJP

回答

0

我明白了爲什麼它沒有工作.. 字符串行是:「EXAMPLE \ n」 但在

while((line=bufReader.readLine()) != null){ 
...} 

line =「EXAMPLE」,因爲readLine()吃掉換行符。 所以我傳遞給readPrevisione()一個StringTokenizer類作爲參數

while((line=bufReader.readLine()) != null){ 
    StringTokenizer st = new StringTokenizer(line); 
    readPrevisione(st,bufReader); 
} 

private void readPrevisione(StringTokenizer st, BufferedReader bufReader) throws IOException, BadFileFormatException{ 
String nomeSettore = st.nextToken().trim(); 
...} 

而且st.nextToken()搜索未包含在「示例」一\ n。這就是爲什麼它不起作用。

0

您正在使用默認的分隔符創建StringTokenizer的,那就是,「空格字符,製表符,換行符,該carriage-返回字符和換頁字符。「

因此,在第一種情況下,您將整個行設置爲「nomeSettore」變量的值,但是當您使用StringTokenizer.nextToken()時,只會向第一個標記的值發送「nomeSettore」。因此,如果您的字符串「行」包含空格,並且在地圖中您將具有不同的鍵值對,「nomeSettore」可以具有不同的值。

你可以看看這個例子:

public class TestSO { 

public static void main(String[] args) { 
    String line = "abcdfs faf afd fa"; 
    StringTokenizer st = new StringTokenizer(line); 
    readPrevisione(st, null); 
    readPrevisione(line, null); 
} 

private static void readPrevisione(StringTokenizer st, BufferedReader bufReader) { 
    String nomeSettore = st.nextToken().trim(); 
    System.out.println(nomeSettore); 
} 

private static void readPrevisione(String st, BufferedReader bufReader) { 
    String nomeSettore = st.trim(); 
    System.out.println(nomeSettore); 
} 

}

它打印作爲輸出:

abcdfs 
abcdfs faf afd fa 
+0

是的,但是..第一行是「EXAMPLE \ n」...所以我不明白錯誤,因爲它應該適用於兩個版本和代碼是相同的。只是更改String行和StringTokenizer參數 – FollettoInvecchiatoJr

+0

什麼你的JUnit測試是?它是否在地圖的全部內容上?它是在一條線上嗎?這關乎你究竟在測試什麼。 –

+0

我用File.txt編輯來讀取和String的相對格式。 – FollettoInvecchiatoJr