Informatik II Aufgabenblatt 6 Gruppen¨ubung
Transcription
Informatik II Aufgabenblatt 6 Gruppen¨ubung
Prof. Dr. Th. Letschert FB MNI TH Mittelhessen StudiumPlus Informatik II Aufgabenblatt 6 Gruppenübung Aufgabe 1 CSV–Dateien sind Textdateien die Zeilen mit “Komma-separierten” Werten bestehen (CSV = Comma Separated Values). CSV-Dateien werden sehr häufig zum Datenaustausch zwischen unterschiedlichen Programmen eingesetzt. Statt des Kommas als Trennzeichen, werden oft auch andere Zeichen verwendet. Im deutschsprachigen Raum ist es in der Regel das Semikolon. Ein typischer Einsatz für CSV-Tabellen ist der Import in und der Export aus Tabellenkalkulationsprogrammen wie MS Excel oder Open Office Calc. Angenommen wir haben eine Tabelle mit den Daten: Personalnummer 6666 1234 7777 Name Maulwurf Dr Hibbert Burns Vorname Hans Julius M. Charles Montgomery Gehalt 5000 30000 150000000 Bei einem Export ins CSV–Format könnte dann eine Datei mit folgendem Inhalt generiert werden: 6666;Maulwurf;Hans;5000 1234;Dr Hibbert;Julius M.;30000 7777;Burns;Charles Montgomery;150000000 Lesen Sie zu CSV den Artikel den Wikipedia-Artikel http://de.wikipedia.org/wiki/CSV (Dateiformat) und erstellen Sie dann eine CSV–Datei mit dem angegebenen Inhalt (oder einem anderen). Verwenden Sie dazu ein Tabellenkalkulationsprogramm ihrer Wahl oder (im Notfall!) einen Texteditor. Aufgabe 2 Der Inhalt einer Datei wird traditionell an der Dateiendung erkannt, also an dem letzten Bestandteil des Dateinamens. Eine CSV–Datei ist danach eine Textdatei mit der Endung .csv. Seit Windows aber – wahrscheinlich zu Recht – meint, dass der typische Benutzer das Konzept einer Dateiendung nicht versteht und darum Unsinn damit treibt, werden Dateiendungen oft versteckt und können nicht mehr unbedingt zum Erkennen eines Dateityps verwendet werden. Statt den Inhalt einer Datei nur an der Dateiendung kenntlich zu machen beginnt man mit Inhaltstypen (auch MIME–Types) zu arbeiten. Einem Konzept, das ursprünglich für die Kennzeichnung von übertragen Daten entwickelt wurde, aber auch für gespeicherte Daten eingesetzt werden kann. Um Nachrichten verschicken zu können, die neben reinem Text auch Bilder, Musik, etc. enthalten können, hat sich die Internet–Gemeinde zu Beginn der 90–er Jahre einen Standard ausgedacht, der Bit–Ströme als Bestandteile von E–Mails eindeutig charakterisiert: den sogenannten MIME–Standard.1 MIME stand dabei ursprünglich für Multipurpose Internet Mail Extension. Der MIME–Standard wurde danach in die Web–Technologie übernommen und ist heute von großer Bedeutung über das Internet hinaus für jeden Transfer von Daten auch mit Hilfe von Dateien. Man spricht vom MIME–Typ oder MIME type manchmal auch vom Internet Media Type. 1. Lesen Sie den Wikipedia–Artikel zu MIME–Typen http://de.wikipedia.org/wiki/Internet Media Type. 1 Zur ersten Multimedia–Mail und der Geburt von MIME siehe http://guppylake.com/∼nsb/mime.html. 2. Sehen Sie sich auch mal die englischsprachige Variante der Seite an. 3. Finden Sie heraus welcher MIME–Typ einer CSV–Datei laut Standard zugeordnet sein sollte. Aufgabe 3 Dateien mit einer bestimmten Endung oder einem bestimmten Datei–Typ (MIME–Typ) können in Java ausfindig gemacht werden. Betrachten Sie folgende Beispiele (Achtung es wird Java 7 vorausgesetzt!): Variante mit Überprüfung der Endung: import import import import java.io.File; java.io.IOException; java.nio.file.Files; java.nio.file.Path; import javax.swing.JFileChooser; import javax.swing.JOptionPane; public class Test { /** * Lokalisiert Datei mit einem der vorgebenen Dateierweiterungen. Text fuer die Dateiauswahl * @param msg Liste von Erweiterungen, von denen eine * @param extensions der Datei zugeornet sein muss Pfad der ausgwaehlten Datei * @return * @throws IOException */ private static Path locateFileWithExtension(String msg, String... extensions) throws IOException { JFileChooser fc = new JFileChooser(); File f = null; Path p = null; while (true) { int returnVal = fc.showDialog(null, msg); if (returnVal == JFileChooser.APPROVE_OPTION) { f = fc.getSelectedFile(); p = f.toPath(); if (Files.isRegularFile(p) && Files.isReadable(p) ) { for (String ext: extensions) { if (p.toString().endsWith(ext)) { return p; } } } JOptionPane.showMessageDialog(null, "Die Datei hat nicht den richtigen Typ"); } else break; } return null; } public static void main(String[] args) throws IOException { Path path = locateFileWithExtension("CSV Datei", ".csv"); JOptionPane.showMessageDialog(null, "Sie haben gewaehlt:" + path); } } Variante mit Überprüfung des Typs: import import import import java.io.File; java.io.IOException; java.nio.file.Files; java.nio.file.Path; 2 import javax.swing.JFileChooser; import javax.swing.JOptionPane; public class Test { /** * Lokalisiert Datei mit einem der vorgebenen MIME-Typen. Text fuer die Dateiauswahl * @param msg * @param contentTypes Liste von Typen, von denen einer der Datei zugeornet sein muss Pfad der ausgwaehlten Datei * @return * @throws IOException */ private static Path locateFileWithType(String msg, String... contentTypes) throws IOException { JFileChooser fc = new JFileChooser(); File f = null; Path p = null; while (true) { int returnVal = fc.showDialog(null, msg); if (returnVal == JFileChooser.APPROVE_OPTION) { f = fc.getSelectedFile(); p = f.toPath(); if (Files.isRegularFile(p) && Files.isReadable(p) ) { for (String type: contentTypes) { if (Files.probeContentType(p).equals(type)) { return p; } } } JOptionPane.showMessageDialog(null, "Die Datei hat nicht den richtigen Typ"); } else break; } return null; } public static void main(String[] args) throws IOException { Path path = locateFileWithType("CSV Datei", "text/csv", "text/comma-separated-values"); JOptionPane.showMessageDialog(null, "Sie haben gewaehlt:" + path); } } Finden Sie heraus welche Variante(n) bei Ihnen eingesetzt werden kann / können um die CSV–Datei zu identifizieren. Das Konzept der Inhaltstypen zur Charakterisierung von Dateiinhalten ist neu. Sie müssen damit rechnen, dass nicht alles unbedingt so wie erwartet funktioniert. Eventuell wird auf Ihrem System ein anderer, als der erwartete Inhaltstyp festgestellt, oder das System liefert gar keinen Inhaltstyp (der Inhaltstyp ist null). Experimentieren Sie! Verwenden Sie eventuell Zwischenausgaben. Fassen Sie dann zusammen: welcher Inhaltstyp wird einer exportierten Tabelle zugeordnet, entspricht dies dem Standard und kann dieser mit Files.probeContentType(path) festgestellt werden. Ist auf Ihrem System nicht Java 7 installiert, dann müssen Sie auf die Prüfung von Inhaltstypen aus einem Programm heraus verzichten. Es bleibt nur der Test auf die Dateiendung. Das Beispiel oben muss dann noch für Java 6 angepasst werden, da Java 6 den Typ Path nicht kennt. Etwa wie folgt: private static File locateFileWithExtension_6(String msg, String... extensions) throws IOException { JFileChooser fc = new JFileChooser(); File f = null; while (true) { 3 int returnVal = fc.showDialog(null, msg); if (returnVal == JFileChooser.APPROVE_OPTION) { f = fc.getSelectedFile(); for (String ext: extensions) { if (f.getName().endsWith(ext)) { return f; } } JOptionPane.showMessageDialog(null, "Die Datei hat nicht den richtigen Typ"); } else break; } return null; } Hausaufgaben Aufgabe 4 Eine CSV–Datei beschreibt / codiert eine Tabelle bestehend aus Zeilen und Spalten. Jede Zeile repräsentiert eine Datensatz (engl. Record ). Jede Spalte definiert einen Wert in diesen Datensätzen. Die erste Zeile wird oft als “Überschriften-Zeile” genutzt: Sie enthält dann die Namen der unterschiedlichen Werte eines Datensatzes. Diese Namen nennt man auch Attribute oder genauer Attributnamen. Eine CSV–Datei stellt dann eine Liste von Datensätzen dar, in dem jeweils einem Attributnamen ein Attributwert zugeordnet wird. Diese Struktur kann in eine entsprechende Datenstruktur von Java eingelesen werden: import import import import import import java.io.File; java.io.IOException; java.nio.file.Files; java.nio.file.Path; java.util.List; java.util.Map; import javax.swing.JFileChooser; import javax.swing.JOptionPane; public class UserInterface { /** * Lokalisiert Datei mit einem der vorgebenen MIME-Typen. Text fuer die Dateiauswahl * @param msg * @param contentTypes Liste von Typen, von denen einer der Datei zugeornet sein muss Pfad der ausgwaehlten Datei * @return * @throws IOException */ private static Path locateFileWithType(String msg, String... contentTypes) throws IOException { //. . . WIE OBEN BZW SO DASSS BEI IHNEN FUNKTIONIERT . . . } public static void main(String[] args) throws IOException { // SO ODER MIT PASSENDEN ANDEREN PARAMETERN ! Path path = locateFileWithType("CSV Datei", "text/csv", "text/comma-separated-values"); System.out.println("Die Datei " + path + "Enthaelt die Datensaetze:"); List<Map<String, String>> records = CSV.readCSVFile(path, ";"); for (Map<String, String> m : records) { System.out.println(m); } } } 4 Mit einer Routine zur Analyse von CSV–Dateien: import import import import import import import import java.io.IOException; java.nio.charset.Charset; java.nio.file.Files; java.nio.file.Path; java.util.ArrayList; java.util.HashMap; java.util.List; java.util.Map; public class CSV { public static List<Map<String, String>> readCSVFile(Path path, String seperator) throws IOException { // erste Zeile / Attribute String[] attributes = null; // Ergebnis: alle Zeilen ausser der ersten List<Map<String, String>> res = new ArrayList<Map<String, String>>(); boolean firstLine = true; // erste Zeile enthaelt Spalten- (=Attribut-) Namen for (String line : Files.readAllLines(path, Charset.defaultCharset())){ if (firstLine) { attributes = line.split(seperator); firstLine = false; continue; } Map<String,String> entry = new HashMap<>(); String[] values = line.split(seperator); int i = 0; for(String a: attributes) { String value = values[i].trim(); entry.put(a, value); i++; if (i == attributes.length || i == values.length) break; } res.add(entry); } return res; } } Java 6 Benutzer verwenden beispielsweise den Scanner zum Einlesen: private static File locateCSVFile_6(String msg) throws IOException { JFileChooser fc = new JFileChooser(); File f = null; while (true) { int returnVal = fc.showDialog(null, msg); if (returnVal == JFileChooser.APPROVE_OPTION) { f = fc.getSelectedFile(); if (f.getName().endsWith(".csv")) { return f; } JOptionPane.showMessageDialog(null, "Die Datei hat nicht den richtigen Typ"); } else break; } return null; } private static List<Map<String, String>> readCSVFile_6(File file, String seperator) throws IOException { // erste Zeile / Attribute String[] attributes = null; 5 // alle Zeilen ausser der ersten List<Map<String, String>> res = new ArrayList<Map<String, String>>(); boolean firstLine = true; // erste Zeile enthaelt Spalten- (=Attribut-) Namen Scanner scan = new Scanner(file); while (scan.hasNextLine()){ String line = scan.nextLine(); if (firstLine) { attributes = line.split(seperator); firstLine = false; continue; } Map<String,String> entry = new HashMap<>(); String[] values = line.split(seperator); int i = 0; for(String a: attributes) { String value = values[i].trim(); entry.put(a, value); i++; if (i == attributes.length || i == values.length) break; } res.add(entry); } scan.close(); return res; } Testen Sie das Programm mit Ihrer CSV–Datei. Verwenden Sie den für Ihr System geeigneten Mechanismus zur Identifikation der CSV–Datei. Erstellen Sie eine Liste aller String–Operationen und aller Datei–Operationen die in der Klasse CSV verwendet werden und informieren Sie sich über deren Wirkung. (API–Doku!) Aufgabe 5 Definieren Sie Klasse Person und erweitern Sie UserInterface derart, dass die aus der Datei eingelesen Informationen in eine Liste von Personen–Objekten gespeichert wird. Die Klasse der Personen soll dabei die zu den Attributen eines Datensatzes passenden Objektvariablen haben: personalnummer, name, vorname, gehalt. 6