Ich habe ein Problem mit dem Einlesen von csv-Dateien mit dem InputStreamReader. Das Problem betrifft hierbei nur csv-Dateien, die mit Excel erstellt oder zuletzt bearbeitet wurden, erstelle ich eine csv mit Umlauten mit Java und öffne sie danach wieder, werden alle Buchstaben richtig eingelesen. Erstelle ich mit Excel eine Datei mit beispielsweise ä;ö;ü;ß wird daraus �;�;�;�- Um das Problem zu umgehen, hab ich mir bereits 2 Ansätze überlegt, bin im Internet aber auf keine vernünftige Lösung dazu gestoßen.
Ansatz 1: Die eingelesenen Strings in Bytes konvertieren und die Bytes für die falschen Umlaute durch die richtigen ersetzen. Dies muss aber bereits während des Einlesens geschehen, weil wenn ich mir die Bytes aus dem String geben lassen, sind es für alle Umlaute die gleichen Bytes.
Ansatz 2: Ein anderes Dateiformat wählen. Leider habe ich bisher kein Dateiformat gefunden, das mit Excel zu bearbeiten ist und leicht einlesbar. Die eingelesene Datei muss mit Excel zu bearbeiten sein.
Mein Java-Code:
//...Auswahl einer Datei per JFileChooserBufferedReader br;ArrayList<String[]> fileData = new ArrayList<String[]>();try { br = new BufferedReader(new InputStreamReader(new FileInputStream(file), Charset.forName("UTF-8"))); String line; for (int i = 0; (line = br.readLine()) != null; i++) { fileData.add(line.split(";")); }} catch (IOException ex) {}//Weiterverarbeitung der Dateien...
Da Excel leider csv-Dateien so verschlüsselt, dass sie nur fehlerhaft eingelesen werden (selbst wenn die Datei unverändert von Excel eingelesen wird, sowohl auf Windows als auch auf Mac), habe ich mich nun entschieden, von csv- auf xml-Dateien umzusteigen. Funktioniert auch alles ganz gut, ich kriege die einzelnen Zellen, allerdings schaffe ich es nicht, einen regulären Ausdruck zu erstellen, der mir nur den Inhalt der Zellen gibt. Aktuell sieht das Auslesen bei mir so aus:
//den String nur auf die Daten reduzieren
Pattern pattern = Pattern.compile("<Table.*?>.*?</Table>");
Matcher matcher = pattern.matcher(fileString);
String tableString = "";
if(matcher.find(0)) {
tableString = matcher.group();
}
//Jede Zeile einzeln abspeichern
pattern = Pattern.compile("<Row.*?>.*?</Row>");
matcher = pattern.matcher(tableString);
ArrayList<String> rows = new ArrayList<String>();
while (matcher.find()) {
rows.add(matcher.group());
}
ArrayList<String[]> fileData = new ArrayList<String[]>();
//Die Zellen erhalten und wenn die Reihe die richtige Anzahl an Zellen hat, speichern
pattern = Pattern.compile("<Cell.*?>.*?<Data.*?>.*?</Data>.*?</Cell>");
for (int i = 0; i < rows.size(); i++) {
matcher = pattern.matcher(rows.get(i));
//Die Zeile muss exakt 4 Zellen haben
String [] rowData = new String [4];
boolean outOfBounds = false;
for (int j = 0;matcher.find()&&!outOfBounds; j++) {
rowData[j] = matcher.group();
if(j>=rowData.length) {
outOfBounds = true;
}
}
if (!outOfBounds) {
fileData.add(rowData);
}
}
Alles anzeigen
Das Problem liegt in Zeile 17, ich habe im Internet die Funktion (?:X) gefunden, die X zum matchen, aber nicht ins Ergebnis mit reinnimmt, wenn ich den regulären Ausdruck aber in (?:<Cell.*?>.*?<Data.*?>)(.*?)(?:</Data>.*?</Cell>) abändere, kriege ich immer noch das gleiche. Ich möchte nur den rot markierten Teil erhalten.
Ich hoffe ihr könnt mir weiterhelfen!