Java Unerklärliche NumberFormatException

Hydrano

Lieutenant
Registriert
März 2008
Beiträge
945
Hallo,
ich bekomme eine NumberFormatException For input string: "1945"
Es geht um ein Programm, welches zufällige "Kundendaten" erstellen soll und dabei auch eine große Datei, mit PLZ und Städten, einließt.

Diese Datei lese ich in eine Map ein:
Code:
Map<String, String> plzStadtMap
Die PLZ und Stadt sind mit einem ';' getrennt, welche ich dann auch erfolgreich splitte und und in der Map ablege.
Nun will ich viele Datensätze Random erzeugen lassen, aber das funktioniert nur dann, wenn 'Random' nicht die erste Zeile bzw. den ersten Datensatz der Map auswählt.
Die aller erste Zeile in der Datei ist:
Wenn dieser Ort vom Random ausgewählt wird, tritt jedes mal die genannte Fehlermeldung auf.
Ich kann es mir einfach nicht erklären. Zumal ist 1945 eine ganz normale Zahl. Es sind keine Leerzeichen davor oder hinter, dennoch habe ich es auch schon mit .trim() versucht. Hat alles bisher nicht geholfen.
Bin so ein bisschen mit den Latein am Ende :freak:

Das hier ist meine Methode zum einlesen der Datei, aber wie gesagt, dort tritt der Fehler ja nicht auf:
Code:
public static Map<String, String> readFilePlzStadt(String filename) {
		Map<String, String> values = new HashMap<>();
		try {
			FileReader fr = new FileReader(filename);
			BufferedReader br = new BufferedReader(fr);

			String line = br.readLine();
			while (line != null) {
				line = line.trim();
				if (!line.isEmpty()) {
					String[] columns = line.split(";");
					values.put(columns[0].trim(), columns[1].trim());
				}
				line = br.readLine();
			}
			br.close();
		} catch (IOException ex) {
			ex.printStackTrace();
		}
		return values;
	}

Hier rufe ich es dann ab, da tritt der Fehler auf (Zeile 12):
Code:
public List<Kunde> generiereKunden(int dataCount, int lastID) {	
		List<Kunde> kunden = new ArrayList<Kunde>();
		lastID += 1;		
		for(int i = 0; i < dataCount; i++) {
			Kunde kunde = new Kunde();
			kunde.setNr(lastID + i);
			kunde.setName(randValueFromList(vornamenList) + " " + randValueFromList(nachnamenList));
			kunde.setStrasse(randValueFromList(strassenList));
			
			String plz = randValueFromList(plzList);
			try{
				kunde.setPlz(Integer.parseInt(plz.trim()));
			} catch (NumberFormatException e) {
				e.printStackTrace();
				new Notification().warnung(e.getLocalizedMessage(), "Fehler");
			}
			if(plzStadtMap.get(plz).length() > 19) {
				kunde.setStadt(plzStadtMap.get(plz.trim()).substring(0, 19));
			}else {
				kunde.setStadt(plzStadtMap.get(plz.trim()));
			}
			
			kunde.setSperre(CreateRandomSperre());			
			kunden.add(kunde);
			System.out.println(kunde);
		}		
		return kunden;
	}

private static <T> T randValueFromList(List<T> list) {
		return list.get(random.nextInt(list.size()));
	}

Als Anhang gibt es nochmal die Textdatei.

Edit:
Das ganze tritt natürlich nicht so oft auf. Bei nur 10 Datensätzen ist es sehr unwahrscheinlich, dass dieser eine ausgewählt wird.
Aber da ich für ein Projekt bis zu 100.000 Datensätze generieren muss, tritt der Fehler dann doch zu oft auf. Zumal es halt immer nur diese 1945 ist bzw. die erste Zeile ist. Wenn ich nämlich die Zeile lösche und eine andere an erste Stelle rückt, dann tritt dort der Fehler auf...

Natürlich funktioniert es Problemlos wenn ich die PLZ als String belassen würde aber die Datenbank später nimmt nur numbers für die plz an und das kann ich auch nicht ändern.
 

Anhänge

Zuletzt bearbeitet:
Ich weiß nicht, ob eine Map die Datenstruktur ist, die am Ende das Ergebnis liefert, das du gerne hättest.

Grundsätzlich besteht der Eintrag in einer Map aus einem Schlüssel (Key) und einem Wert (Value). So wie du deine Map deklariert hast, sind sowohl die Schlüssel als auch Werte vom Typ String. Über die get Methode einer Map erhält man immer den Wert den man unter dem Schlüssel, den man der get Methode mitgibt, abgelegt hat. Wenn man die Schlüssel vom Typ String hat und dann über einen Integer Wert (ich denke mal aus random.nextInt kommt ein solcher raus) einen Wert aus deiner Map holen möchte wird man den Wert null erhalten, der nicht in eine Zahl gewandelt werden kann. Sollte widererwarten dennoch ein Wert rauskommen, wäre das der Teil hinter dem Semikolon - also keine Postleitzahl. Um mit den Postleitzahlen zu arbeiten müsste man wenn überhaupt das keySet der Map durchgehen.

Daher -> Warum definierst du die Schlüssel als String und nicht direkt als Integer und wandelst die Daten bereits beim Hinzufügen in die Map. Dazu die Anmerkung unter einem eindeutigen Schlüssel in der Map kann man nur einen "Wert" ablegen. Dein Textfile lässt sich so nicht ablegen. Statt einem einfachen String müsste eine Menge von Strings zu einer Postleitzahl abgelegt werden.
 
Zuletzt bearbeitet:
Das erste Zeichen deiner Textdatei ist U+FEFF, das "zero-width non-break space". Das wird nicht dargestellt und wird am Anfang von Unicode Text verwendet um die Endianess erkennen zu können.
Du musst das also ignorieren, am besten wäre es, wenn die Java Reader das bei dem richtigen FileEncoding einfach wegfiltern, da weiß ich nicht wie die sich verhalten. Sonst kannst du bei der ersten Zeile einfach den ersten Char weglassen oder jede Zeile mit regexen bearbeiten um das zu entfernen.

Abgesehen davon würde ich dir nahelegen englischen Code zu schreiben, programmieren ist sehr international und du weißt nie wer mal den Code sieht.
 
NemesisFS schrieb:
Das erste Zeichen deiner Textdatei ist U+FEFF, das "zero-width non-break space". Das wird nicht dargestellt und wird am Anfang von Unicode Text verwendet um die Endianess erkennen zu können.
Du musst das also ignorieren, am besten wäre es, wenn die Java Reader das bei dem richtigen FileEncoding einfach wegfiltern, da weiß ich nicht wie die sich verhalten. Sonst kannst du bei der ersten Zeile einfach den ersten Char weglassen oder jede Zeile mit regexen bearbeiten um das zu entfernen.

Abgesehen davon würde ich dir nahelegen englischen Code zu schreiben, programmieren ist sehr international und du weißt nie wer mal den Code sieht.

Danke das werde ich direkt mal ausprobieren.
Meist arbeite ich auch ausschließlich mit englischen Bezeichnungen, nur bei Studienprojekten eben nicht. Unser Prof steht auf deutsche Variablennamen und deutsche Kommentierung :rolleyes:
 
Hydrano schrieb:
Meist arbeite ich auch ausschließlich mit englischen Bezeichnungen, nur bei Studienprojekten eben nicht. Unser Prof steht auf deutsche Variablennamen und deutsche Kommentierung :rolleyes:

Oh Gott... Mein Beileid.
 
Apache Commons hat einen BOMInputStream, mit dem du einfach Dateien mit Byte Order Mark einlesen kannst, ohne es zuerst manuell entfernen zu müssen.

Du solltest außerdem daran denken, dass es in DE Postleitzahlen gibt, die mit 0 beginnen. Wenn du die als Int behandelst, dann fällt die 0 weg. Kann sein, dass es bei uns nur 5-stellige PLZs gibt und du somit später einfach erkennen kannst, wann du die 0 wieder manuell dranhängen musst, aber für andere Länder klappt das nicht. String ist die bevorzugte Repräsentation für Postleitzahlen.
 
crvn075 schrieb:
Du solltest außerdem daran denken, dass es in DE Postleitzahlen gibt, die mit 0 beginnen. Wenn du die als Int behandelst, dann fällt die 0 weg. Kann sein, dass es bei uns nur 5-stellige PLZs gibt und du somit später einfach erkennen kannst, wann du die 0 wieder manuell dranhängen musst, aber für andere Länder klappt das nicht. String ist die bevorzugte Repräsentation für Postleitzahlen.

this +1
 
+2

Generell gilt bei der Entscheidung welcher Datentyp: Wenn es kein numerischer Wert ist (der etwas beziffert oder mit dem man rechnen möchte), sondern eine folge von Ziffern, ist es kein Integer, Float, Decimal oder ähnliches. Weil es aussieht wie eine Zahl ist es noch keine. Über die korrekte Enscheidung sparst du dir einige Probleme.

Dann würde ich überdenken, ob
private static <T> T randValueFromList(List<T> list)
wirklich so generisch sein muss, oder ob du nicht eine Liste von Strings übergeben und entsprechend einen String zurückgeben kannst. Insgesamt vermeidest du so durch präziseren (aus meiner Sicht saubereren) Code dein Problem von vornherein und brauchst garnicht erst drumherum arbeiten.

Ist mir nur zufällig aufgefallen:
Zeile 9 im oberen Snippet ist an der Stelle unnötig. Da du die Columns separat trimst, ist das ein trim() zu viel.
 
Zurück
Oben