2017-06-01 2 views
0

Ich hatte eine Datei zu lesen und mit diesem Code gelang es mir meine JUnit-Tests. Wie Sie sehen können, übergebe ich die String-Zeile als Parameter an die readPrevisione (...) -Methode.String oder StringTokenizer mit einem Reader?

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

hier mit dem gleichen Code, anstatt die Leseleitung als Parameter übergeben wird, gebe ich die StringTokenizer, die bereits die Zeile gelesen hat. Es sollte wie oben funktionieren, aber meine JUnit-Tests schlagen fehl. Was habe ich falsch gemacht?

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

} 

EDIT: Hier ist die File.txt, die ich lesen will.

Und hier ist ein Beispiel für eine meines JUnit-Test:

@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

Beide Versionen enthalten eine potentielle NPE, wenn 'readLine()' einen unerwarteten Nullwert zurückgibt. – EJP

+0

Wenn readLine() null zurückgibt, bedeutet dies, dass die Datei.txt leer ist. Im Abschnitt "Controller" des Programms (hier nicht gezeigt), wenn die HashMap leer ist, wird eine Ausnahme ausgelöst. Aber das ist nicht der Punkt. Das Problem liegt zwischen StringTokenizer und String als Parameter übergeben. – FollettoInvecchiatoJr

+0

Es bedeutet, dass die Datei leer ist * oder * enthält keine Zeile "FINE". Ich habe das als Kommentar gepostet, nicht als Antwort. – EJP

Antwort

0

Ich habe verstanden, warum es nicht funktioniert .. Die Zeichenfolgelinie war: "BEISPIEL \ n" aber nach

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

line = "BEISPIEL", weil die readLine() die Newline isst. So kam ich auf die readPrevisione() einen StringTokenizer als Parameter

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(); 
...} 

Und st.nextToken() Suche nach einem \ n, die nicht in "Beispiel" enthalten ist. Deshalb hat es nicht funktioniert.

0

Sie erstellen StringTokenizer mit Standardtrennzeichen, das heißt, „das Leerzeichen, das Tab-Zeichen, die Newline-Zeichen, die Fahrbahn return-Zeichen und das Feed-Zeichen. "

Also im ersten Fall setzen Sie als Wert der "nomeSettore" Variable die ganze Zeile, aber wenn Sie StringTokenizer.nextToken() verwenden, geben Sie "nomeSettore" nur den Wert des ersten Tokens. So kann "nomeSettore" unterschiedliche Werte haben, wenn Ihre "Zeile" whitespaces enthält und Sie verschiedene Schlüssel/Wert-Paare in Ihrer Map haben.

Sie können an diesem Beispiel einen Blick:

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

}

Es als Ausgabe druckt:

abcdfs 
abcdfs faf afd fa 
+0

Ja, aber .. Die erste Zeile ist "BEISPIEL \ n" ... Also ich verstehe den Fehler nicht, weil es mit beiden Versionen arbeiten sollte und der Code ist der gleiche .. Ändert nur die String-Zeile und StringTokenizer Parameter – FollettoInvecchiatoJr

+0

Was? ist Ihr JUnit-Test? Ist es auf dem gesamten Inhalt der Karte? Ist es in einer einzigen Zeile? Es geht nur darum, was Sie gerade testen. –

+0

Ich bearbeitet mit der Datei.txt, um zu lesen und das relative Format von String. – FollettoInvecchiatoJr