Foliensatz 4

Werbung
Informatik II
Dateien
Seite 1
Th Letschert, THM
Dateien - Konzept
Datei
Externer Datenspeicher
CPU: Programmausführung
Hauptspeicher: Programmcode und -Daten, direkt zugreifbar von CPU
Festplatte etc.: nur indirekt zugreifbar über Betriebssystem-Aufrufe
Extern
Intern
CPU / Prozessor
Programmausführung
Hauptspeicher
Festplatte
Programm-Code und -Daten
Betriebssystem
Seite 2
Dateien - Konzept
Datei – rein virtuelles Konstrukt auf verschiedenen Abstraktionsebenen
Abstraktionsebenen
Platte:
Magnetisierte Spuren, in Zylinder organisiert
Plattencontroller:
nummerierte Datenblöcke (von jeweils z.B. 512 Byte)
Betriebssystem:
(BS-) Datei = (scheinbar) zusammenhängender
beliebig und variabel großer Datenbereich,
nach Konventionen des Betriebssystems nutzbar
Programm:
(Programm-) Datei = (scheinbar) zusammenhängender
beliebig und variabel großer Datenbereich,
nach Konventionen der Programmiersprache nutzbar
Ababd
ahuwe
diuhw
Programmdatei
(Programminterne
Repräsentation.)
Systemaufruf
Programm
Programm-API
Betriebssystem
BS-Datei
(BS-internere Rep.)
Seite 3
Daten
Dateien - Konzept
Datei-Repräsentant in Java
Ababd
ahuwediuh
bis Java 1.6:
java.io.File
ab Java 1.7:
java.nio.file.Path
Programm
Programm-API
Betriebssystem
Ab Java 7 stehen beide Varianten zur Verfügung. Es sollte
aber i.A. die neuere Variante java.nio.file.Path verwendet
werden.
Gelegentlich muss aber auch bei Java 7 auf die Klasse
java.io.File zurück gegriffen werden. (z.B. bei Verwendung
des FileChooser.)
Seite 4
Dateien – Verwendung / lesen
Datei-Inhalt zeilenweise – mit der Klasse Scanner – lesen
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Read_V6 {
public static void main(String[] args) throws FileNotFoundException {
File f = new File("blubber.txt");
}
}
Scanner scan = new Scanner(f);
while (scan.hasNextLine()) {
System.out.println(scan.nextLine());
}
import
import
import
import
Java alle Versionen
java.io.IOException;
java.nio.file.Path;
java.nio.file.Paths;
java.util.Scanner;
public class Read_V7 {
public static void main(String[] args) throws IOException {
Path p = Paths.get("blubber.txt");
}
Scanner scan = new Scanner(p);
while (scan.hasNextLine()) {
System.out.println(scan.nextLine());
}
ab Java 1.7
}
Seite 5
Dateien – Verwendung / lesen
Datei-Inhalt zeilenweise einlesen
import
import
import
import
import
java.io.IOException;
java.nio.charset.Charset;
java.nio.file.Files;
java.nio.file.Path;
java.nio.file.Paths;
public class Read_V7_a {
public static void main(String[] args) throws IOException {
Path path = Paths.get("test.txt");
int i = 0;
for ( String line: Files.readAllLines(
path,
Charset.defaultCharset()) ) {
System.out.println("Zeile "+ ++i + line);
}
}
ab Java 1.7
System.out.println("Die Datei enthält " + i + " Zeilen");
java.nio.file.Files
}
ist eine Helferklasse mit
allerlei Nützlichem in Bezug
auf Datei-Verarbeitung.
java.nio.file.Paths
ist eine Helferklasse mit
Nützlichem in Bezug auf
Datei-Operationen.
Seite 6
Dateien – Verwendung / lesen
Datei-Inhalt komplett als String einlesen
import
import
import
import
import
java.io.IOException;
java.nio.charset.Charset;
java.nio.file.Files;
java.nio.file.Path;
java.nio.file.Paths;
public class Read_V7_b {
public static void main(String[] args) throws IOException {
Path path = Paths.get("blubber.txt");
String content = new String(
Files.readAllBytes(path),
Charset.defaultCharset());
ab Java 1.7
System.out.println(content);
}
}
Verwendet aus der Klasse Files:
byte[] readAllBytes(Path path)
und den Konstruktor der Klasse String:
String(byte[] bytes, Charset charset)
Seite 7
Dateien – Verwendung / Auswahl
Datei-Auswahl mit Auswahldialog – Java 6 Variante
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import javax.swing.JFileChooser;
public class Choose_V6 {
public static void main(String[] args) throws FileNotFoundException {
File f = null;
JFileChooser fc = new JFileChooser();
int chooseResult = fc.showDialog(null, "Bitte Datei auswählen");
if (chooseResult == JFileChooser.APPROVE_OPTION) {
f = fc.getSelectedFile();
}
if (f != null) {
Scanner scan = new Scanner(f);
while (scan.hasNextLine()) {
System.out.println(scan.nextLine());
}
}
}
}
Seite 8
Dateien – Verwendung / Auswahl
Datei-Auswahl mit Auswahldialog – Java 7 Variante
import
import
import
import
java.io.File;
java.io.IOException;
java.nio.file.Path;
java.util.Scanner;
import javax.swing.JFileChooser;
public class Choose_V7 {
public static void main(String[] args) throws IOException {
}
File f = null;
JFileChooser fc = new JFileChooser();
int chooseResult = fc.showDialog(null, "Bitte Datei auswählen");
if (chooseResult == JFileChooser.APPROVE_OPTION) {
f = fc.getSelectedFile();
}
Wechsel zwischen den V-6 und V-7
if (f != null) {
Repräsentanten:
Path p = f.toPath();
Path path = file.toPath()
Scanner scan = new Scanner(p);
while (scan.hasNextLine()) {
File file = path.toFile();
System.out.println(scan.nextLine());
}
}
}
Seite 9
Dateien – Verwendung / schreiben
Datei schreiben – Java 6 Variante
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
public class Write_V6 {
public static void main(String[] args) throws IOException {
String filePath = "balbla.txt";
PrintWriter pw = new PrintWriter(
new FileWriter(filePath));
pw.println("Hallo");
pw.println("Welt!");
pw.close();
}
Datei mit Printwriter verbinden
Datei schließen nicht vergessen!
}
Seite 10
Dateien – Verwendung / schreiben
Datei schreiben – Java 7 Variante
import
import
import
import
import
java.io.IOException;
java.io.PrintWriter;
java.nio.charset.Charset;
java.nio.file.Files;
java.nio.file.Paths;
public class Write_V7 {
public static void main(String[] args) throws IOException {
String filePath = "balbla.txt";
PrintWriter pw = new PrintWriter(
Files.newBufferedWriter(
Paths.get(filePath),
Charset.defaultCharset()));
}
pw.println("Hallo\n");
pw.println("Welt!\n");
pw.close();
Datei mit Printwriter verbinden
Angabe in welchem Zeichensatz der Text
codiert werden soll. Z.B: Zeichensatz des
Systems oder UTF-8
- Charset.defaultCharset()
- Charset.forName("UTF-8"))
}
Seite 11
Dateien – Verwendung / schreiben
Datei schreiben – Java 7
Hallo Welt!
balbla.txt
import
import
import
import
import
vorher
java.io.IOException;
java.nio.file.Files;
java.nio.file.Path;
java.nio.file.Paths;
java.nio.file.StandardOpenOption;
public class Write_V7a {
public static void main(String[] args) throws IOException {
Path path = Paths.get("balbla.txt");
String text = "Das ist ein zusätzlicher Text\nMit Zeilenvorschub!";
byte[] bytes = text.getBytes("UTF-8");
Files.write(path, bytes, StandardOpenOption.APPEND);
}
}
Anhängendes Schreiben eines Strings auf eine Datei.
Hallo Welt!
Das ist ein zusätzlicher Text
Mit Zeilenvorschub!
java.nio.file.StandardOpenOption
- APPEND
- CREATE
-…
Siehe API-Dok.
balbla.txt
Seite 12
nachher
Dateien – Verwendung / Dateioperationen
Dateien erzeugen, kopieren, löschen – Java 7
import
import
import
import
import
import
java.io.IOException;
java.nio.file.Files;
java.nio.file.Path;
java.nio.file.Paths;
java.nio.file.StandardCopyOption;
java.nio.file.StandardOpenOption;
public class CreateCopyDelete {
public static void main(String[] args) throws IOException {
Path path_1 = Paths.get("D:\\Users\\Thomas\\datei_1.txt");
Path path_2 = Paths.get("D:\\Users\\Thomas\\datei_2.txt");
// 1. Datei erzeugen
Files.createFile(path_1);
// 1. Datei fuellen
Files.write(
path_1,
"Ein wenig Text.\nAls Inhalt der Datei.\n".getBytes(),
StandardOpenOption.WRITE);
// 1. -> 2. Datei kopieren
Files.copy(path_1, path_2, StandardCopyOption.REPLACE_EXISTING);
}
// 1. Datei loeschen
Files.delete(path_1);
}
Seite 13
Dateien – Verwendung / anlysieren
Datei analysieren – nur Java 7
import
import
import
import
java.io.File;
java.io.IOException;
java.nio.file.Files;
java.nio.file.Path;
import javax.swing.JFileChooser;
public class AnalyseFile {
public static void main(String[] args) throws IOException {
File f = null;
JFileChooser fc = new JFileChooser();
int chooseResult = fc.showDialog(null, "Bitte Datei auswählen");
if (chooseResult == JFileChooser.APPROVE_OPTION) {
f = fc.getSelectedFile();
}
if (f != null) {
Path p = f.toPath();
if (Files.isRegularFile(p)) {
System.out.println("Die Datei ist "
+ (Files.isExecutable(p) ? " ausfuehrbar" : " ")
+ (Files.isReadable(p) ? " lesbar" : " ")
+ (Files.isWritable(p) ? " schreibbar" : " "));
System.out.println("Der Dateityp ist: "
+ Files.probeContentType(p));
}
}
}
}
Seite 14
Texte analysieren
Inhalt einer (Text-) Datei analysieren – alle Java-Versionen
Datei-Inhalt = Text = String
Standardverfahren der Textanalyse in Java:
– StringTokenizer, StreamTokenizer
veraltet
– Scanner-Klasse
Text strukturiert lesen (Wort für Wort, Zeile für Zeile, etc.)
– String.split Methode
Text an bestimmten Zeichen aufspalten
– Klassen Pattern und Matcher
für Fortgeschrittene
Seite 15
Texte analysieren – Scanner
Scanner-Klasse
kann Texte (Strings) in beliebige Einheiten aufspalten und Einheit für Einheit zur
Verfügung stellen
verschiedene Arten von Text-Quellen sind dabei möglich.
import java.util.Scanner;
public class Scan {
public static void main(String[] args) {
String s = "Dies ist ein Text.\nEr besteht aus\nWorten und Zeilen.\n";
Scanner scanString = new Scanner(s);
while (scanString.hasNext()) {
System.out.println(scanString.next());
}
System.out.println();
ScanString.close();
}
}
scanString = new Scanner(s);
while (scanString.hasNextLine()) {
System.out.println(scanString.nextLine());
}
ScanString.close();
Wortweise aus einem
String lesen
Zeilenweise aus einem
String lesen
Dies
ist
ein
Text.
Er
besteht
aus
Worten
und
Zeilen.
Dies ist ein Text.
Er besteht aus
Worten und Zeilen.
Scanner stellt diverse next...-Methoden zur
Verfügung um den nächsten Text
entsprechend einem bestimmten Typ zu
analysieren. Siehe API-Doku.
Seite 16
Texte analysieren – Scanner
Scanner-Klasse
kann Texte (Strings) in beliebige Einheiten aufspalten und Einheit für Einheit zur
Verfügung stellen
verschiedene Arten von Text-Quellen sind dabei möglich.
import
import
import
import
java.io.IOException;
java.nio.file.Path;
java.nio.file.Paths;
java.util.Scanner;
public class Scan {
public static void main(String[] args) throws IOException {
Path path = Paths.get("/home/thomas/tmp/blubber1.txt");
Scanner scanFile = new Scanner(path);
while (scanFile.hasNext()) {
System.out.println(scanFile.next());
}
System.out.println();
scanFile.close();
scanFile = new Scanner(p);
while (scanFile.hasNextLine()) {
System.out.println(scanFile.nextLine());
}
}
Wortweise aus einer Datei lesen
Zeilenweise aus einer Datei lesen
}
Seite 17
Texte analysieren – String split
Split-Methode der Klasse String
kann Texte (Strings) in beliebige Einheiten aufspalten und Einheit für Einheit zur
Verfügung stellen.
Ähnlich zu Scanner
es können allerdings nur Texte, die in Strings liegen, zerlegt werden
und die Zerlegung erfolgt „in einem Schritt“.
"Abc die Katze lief im Schnee."
public class Split {
public static void main(String[] args) throws IOException {
String s = "Abc die Katze lief im Schnee.";
String[] sParts = s.split("\\s");
}
System.out.println(Arrays.asList(sParts));
["Abc", "die", "Katze", "lief", "im", "Schnee."]
}
"\\s": Trenner: jede Folge von „weiße Zeichen“,
Leerzeichen, Tabs, etc. (ein regulärer Ausdruck)
Seite 18
Texte analysieren – Reguläre Ausdrücke
Regulärer Ausdruck
➢
➢
➢
➢
➢
Ein Textmuster
Vielfältige Verwendung bei der Textanalyse (unabhängig von
Programmiersprachen)
Wird als Konzept von allen (brauchbaren) anwendungsnahen
Programmiersprachen angeboten
Scanner und String.split verwenden reguläre Ausdrücke zur Definition der
Trenner.
Reguläre Basis-Ausdrücke in Java, Beispiele:









x
jedes Zeichen ist ein Muster das für sich selbst steht
[xy]
eine Klasse, ein x oder ein y
regEx1 | regex2 ein Text der zu regEx1 oder regEx2 passt
\\d
eine Ziffer (= "[0123456789]" = "[0-9]" )
\\s
ein weißes Zeichen
\\w
ein Wortzeichen (Buchstabe, Ziffer oder Unterstrich)
.
ein einziges beliebiges Zeichen
regEx1*
ein Text, der zu regEx1 passt, beliebig oft wiederholt
\\.
ein Punkt, Sonderzeichen wie Punkt brauchen „Escape“-Zeichen
Seite 19
Texte analysieren – Reguläre Ausdrücke
Regulärer Ausdruck
Beispiel:
public class Match {
public static void main(String[] args) {
String[] strings = {
"Abc die Katze lief im Schnee.",
"Peter schlief im Klee.",
"Klausi trinkt gerne Tee mit Ruhm.",
"Die Katze liebt keinen See."};
Katze
String[] pattern = {"Katze", ".*ee.*"};
Etwas mit zwei e-s
for (String s: strings) {
System.out.println(s);
for (String word : s.split("\\s")) {
for (String pat: pattern) {
if (word.matches(pat)) {
System.out.println(
"\tenthält das Wort "
+ word + " das zu "
+ pat + " passt");
}
}
Abc die Katze lief im Schnee.
enthält das Wort Katze das zu Katze passt
enthält das Wort Schnee. das zu .*ee.* passt
Peter schlief im Klee.
enthält das Wort Klee. das zu .*ee.* passt
Klausi trinkt gerne Tee mit Ruhm.
enthält das Wort Tee das zu .*ee.* passt
Die Katze liebt keinen See.
enthält das Wort Katze das zu Katze passt
enthält das Wort See. das zu .*ee.* passt
}
}
}
Seite 20
Texte analysieren – Beispiel CVS-Datei
CSV-Datei
CSV: Comma Separated Values
Standard-Format für Daten in Textform – ein (wichtiges) Format von sehr vielen
Import- / Export-Format für Excel (und viele andere Programme)
Tabellen ~ Textdateien
– Zeilen der Tabelle :
– Zellen der Tabelle :
Zeilen der Textdatei
durch Komma (Semikolon, Tab, …)
getrennte Werte in einer Zeile
Seite 21
Texte analysieren – Beispiel CVS-Datei
CSV-Datei einlesen : Datei auswählen
static Path locateCSVFile(String msg) 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)
&& (Files.probeContentType(p).equals("text/csv")
|| Files.probeContentType(p).equals("text/comma-separated-values")
)) {
return p;
}
JOptionPane.showMessageDialog(null, "Die Datei ist keine CSV Datei!");
} else break;
}
return null;
}
Seite 22
Texte analysieren – Beispiel CVS-Datei
CSV-Datei einlesen : naive Analyse
static List<Map<String, String>> readCSVFile(Path path, String seperator) throws IOException {
// erste Zeile / Attribute
String[] attributes = null;
// 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;
}
Naive Analyse: CSV-Dateien können eine sehr komplexe
Map<String,String> entry = new HashMap<>();
Struktur ausweisen, vor allem dann, wenn Zellen Werte
String[] values = line.split(seperator);
enthalten, in denen der Trenner vorkommt.
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;
Excel speichert Tabellen in Binärformat. (Unterschiedlich mit den
Versionen wechselnd, teilweise geheim.)
Zum Lesen und Schreiben muss man dieses Format genau kennen.
Die Java-API enthält keine entsprechenden Klassen. Man kann aber
frei verfügbare Open-Source Bibliotheken verwenden, z.B.: Apache
POI (http://poi.apache.org/).
Seite 23
Dateien – Binär-Dateien
Text-Dateien und Binär-Dateien
alle Dateien enthalten Binärdaten!
Textdatei
enthält Bytes deren Bedeutung Zeichen sind
Bedeutung der Bytes als Zeichen wird vom Zeichensatz (Charset) definiert
Eingelesene Bytes müssen in programm-interne Zeichen umgewandelt werden
Zeichen im Programm sind ebenfalls Bytes, aber meist nicht in der gleichen
Codierung wie die vom Zeichensatz definierte
Bitmuster A
Lesen/Schreiben
Umcodieren
Bedeutet nach den
Konventionen der
Sprache
Bedeutet im
Zeichensatz cs
Datei
Bitmuster B
Zeichen z
Hauptspeicher / CPU
Seite 24
Zeichensätze sind
von großer
Bedeutung
Dateien – Binär-Dateien
Text-Dateien und Binär-Dateien
alle Dateien enthalten Binärdaten!
Binärdatei
Enthält Bytes deren Bedeutung von keiner Text-Konvention definiert ist
Die Bedeutung der Bytes wird von der Anwendung definiert
Eine Umwandlung der Bitmuster beim Lesen und Schreiben
 Findet nicht statt: Die Bitmuster werden so gespeichert, wie sie im
Hauptspeicher zu finden sind
 Findet statt: Die Bitmuster werden beim Lesen decodiert und beim
Schreiben codiert.
Seite 25
Dateien – Binär-Dateien
Binär-Dateien / Beispiel: Daten binär einlesen und ausgeben
import
import
import
import
import
import
import
import
java.io.File;
java.io.IOException;
java.io.InputStream;
java.io.OutputStream;
java.nio.charset.Charset;
java.nio.file.Files;
java.nio.file.Path;
java.nio.file.StandardOpenOption;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
public class ByteIO {
public static void main(String[] args) throws IOException {
Path pathI = ...
Path pathO = ...
InputStream is = Files.newInputStream(pathI, StandardOpenOption.READ);
OutputStream os = Files.newOutputStream(pathO, StandardOpenOption.WRITE);
byte[] bytes = new byte[1024];
int size = is.read(bytes);
is.close();
// Bytes einlesen (maximal 1024 Bytes)
// Bytes als entsprechend dem aktuellen Zeichensatz decodieren
String s = new String(bytes, 0, size, Charset.defaultCharset());
System.out.println(s);
os.write(bytes, 0, size);
os.close();
// Bytes schreiben
}
}
Seite 26
Dateien – Binär-Dateien
Binär-Dateien / Serialisierung
alle Dateien enthalten Binärdaten!
Serialisierung / Deserialisierung
Serialisieren: Die Bits von Objekten werden unverändert aus dem Hautspeicher
in eine Datei geschrieben.
Deserialisieren: Die Bits von Objekten werden unverändert von einer Datei in
den Hauptspeicher kopiert
Vorteil: Schnell
Nachteil: Nicht Portabel, das Datenformat an Java gebunden
Objekt
Speicher
1
0
1
1
1
0
1
0
0
1
Seite 27
Datei
Dateien – Binär-Dateien
Binär-Dateien / Beispiel Serialisierung, Deserialisierung
Markierung: Serialisieren erlaubt!
Kontrolle der Version der Definition
class Person implements Serializable {
}
private static final long serialVersionUID = 1L;
private String name;
private String vorName;
public Person(String vorName, String name) {
this.name = name;
this.vorName = vorName;
}
@Override
public String toString() {
return "Person["+vorName+" "+name+"]";
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
Person[] personen_1 = {
new Person("Karl", "Napp"), new Person("Karla", "Kahl")}; Das zu speichernde Objekt (ein
Path path = ...
ObjectOutputStream os = new ObjectOutputStream(
Files.newOutputStream(path,
StandardOpenOption.WRITE,
StandardOpenOption.TRUNCATE_EXISTING));
os.writeObject(personen_1);
os.close();
Datei öffnen
Objekt speichern
ObjectInputStream is = new ObjectInputStream(
Files.newInputStream(path,
StandardOpenOption.READ));
Person[] personen_2 = (Person[]) is.readObject();
is.close();
for (Person p: personen_2) { System.out.println(p); }
}
Seite 28
Datei öffnen
Objekt einlesen
Array)
Dateien – Binär-Dateien
Binär-Dateien / standardisierte Formate
universelle Formate: z.B.: MP3
anwendungs-spezifische Formate, z.B. Speicherformat von Word, Excel
„lokale“ Formate: Verabredung zwei Partner
Vergleich zu Textdateien
– Vorteil: Speicherung kompakter, schreiben / lesen schneller
– Nachteil: schwer zu entziffern (kann auch Vorteil sein)
Seite 29
Herunterladen