File
. Über seine Arbeit können Sie hier lesen . Doch in Java 7 beschlossen die Entwickler der Sprache, die Art und Weise zu ändern, wie sie mit Dateien und Verzeichnissen arbeiten. Dies lag daran, dass die Klasse File
eine Reihe von Nachteilen aufwies. Beispielsweise gab es keine Methode copy()
, mit der Sie eine Datei von einem Speicherort an einen anderen kopieren könnten (eine scheinbar eindeutig benötigte Funktion). Darüber hinaus File
verfügte die Klasse über zahlreiche Methoden, die boolean
-Werte zurückgaben. Wenn ein Fehler auftritt, gibt eine solche Methode „false“ zurück , anstatt eine Ausnahme auszulösen, was die Diagnose von Fehlern und die Ermittlung ihrer Ursachen sehr erschwert. Anstelle einer einzigen Klasse File
erschienen bis zu drei Klassen: Paths
, Path
und Files
. Genauer gesagt Path
ist dies eine Schnittstelle, keine Klasse. Lassen Sie uns herausfinden, wie sie sich voneinander unterscheiden und warum jeder von ihnen benötigt wird. Beginnen wir mit der einfachsten Sache – Paths
.
Wege
Paths
ist eine sehr einfache Klasse mit einer einzigen statischen Methode get()
. Es wurde ausschließlich erstellt, um ein Objekt des Typs aus der übergebenen Zeichenfolge oder URI abzurufen Path
. Es hat keine andere Funktionalität. Hier ein Beispiel seiner Arbeit:
import java.nio.file.Path;
import java.nio.file.Paths;
public class Main {
public static void main(String[] args) {
Path testFilePath = Paths.get("C:\\Users\\Username\\Desktop\\testFile.txt");
}
}
Nicht die schwierigste Klasse, oder? :) Nun, da wir ein Objekt vom Typ haben Path
, wollen wir herausfinden, was es ist Path
und warum es benötigt wird :)
Weg
Path
ist im Großen und Ganzen ein neu gestaltetes Analogon von File
. Es ist viel einfacher, damit zu arbeiten als mit File
. Erstens wurden viele nützliche (statische) Methoden daraus entfernt und in die Klasse verschoben Files
. ZweitensPath
wurden die Rückgabewerte der Methoden geordnet . In der Klasse File
gaben die Methoden dies String
, das boolean
, das zurück File
– das war nicht leicht herauszufinden. Beispielsweise gab es eine Methode getParent()
, die den übergeordneten Pfad für die aktuelle Datei als Zeichenfolge zurückgab. Aber gleichzeitig gab es eine Methode getParentFile()
, die dasselbe zurückgab, aber in Form eines Objekts File
! Das ist eindeutig überflüssig. Daher geben Path
die Methode getParent()
und andere Methoden zum Arbeiten mit Dateien in der Schnittstelle einfach ein Objekt zurück Path
. Keine unzähligen Optionen – alles ist einfach und unkompliziert. Welche nützlichen Methoden gibt es Path
? Hier sind einige davon und Beispiele ihrer Arbeit:
-
getFileName()
– gibt den Dateinamen aus dem Pfad zurück; -
getParent()
– gibt das „übergeordnete“ Verzeichnis in Bezug auf den aktuellen Pfad zurück (d. h. das Verzeichnis, das im Verzeichnisbaum höher liegt); -
getRoot()
– gibt das „Root“-Verzeichnis zurück; das heißt, derjenige, der sich ganz oben im Verzeichnisbaum befindet; -
startsWith()
,endsWith()
– Überprüfen Sie, ob der Pfad mit dem übergebenen Pfad beginnt/endet:import java.nio.file.Path; import java.nio.file.Paths; public class Main { public static void main(String[] args) { Path testFilePath = Paths.get("C:\\Users\\Username\\Desktop\\testFile.txt"); Path fileName = testFilePath.getFileName(); System.out.println(fileName); Path parent = testFilePath.getParent(); System.out.println(parent); Path root = testFilePath.getRoot(); System.out.println(root); boolean endWithTxt = testFilePath.endsWith("Desktop\\testFile.txt"); System.out.println(endWithTxt); boolean startsWithLalala = testFilePath.startsWith("lalalala"); System.out.println(startsWithLalala); } }
Konsolenausgabe:
testFile.txt
C:\Benutzer\Benutzername\Desktop
C:\
true
falseAchten Sie darauf, wie die Methode funktioniert
endsWith()
. Es prüft, ob der aktuelle Pfad mit dem übergebenen Pfad endet . Es liegt am Pfad und nicht an der Zeichenmenge .Vergleichen Sie die Ergebnisse dieser beiden Aufrufe:
import java.nio.file.Path; import java.nio.file.Paths; public class Main { public static void main(String[] args) { Path testFilePath = Paths.get("C:\\Users\\Username\\Desktop\\testFile.txt"); System.out.println(testFilePath.endsWith("estFile.txt")); System.out.println(testFilePath.endsWith("Desktop\\testFile.txt")); } }
Konsolenausgabe:
Falsch
RichtigSie müssen der Methode den vollständigen Pfad übergeben
endsWith()
und nicht nur eine Reihe von Zeichen: Andernfalls ist das Ergebnis immer falsch , auch wenn der aktuelle Pfad tatsächlich mit einer solchen Zeichenfolge endet (wie im Fall von „estFile.txt “ im Beispiel oben).Darüber hinaus gibt es
Path
eine Gruppe von Methoden, die das Arbeiten mit absoluten (vollständigen) und relativen Pfaden vereinfacht .
-
boolean isAbsolute()
— gibt true zurück , wenn der aktuelle Pfad absolut ist:import java.nio.file.Path; import java.nio.file.Paths; public class Main { public static void main(String[] args) { Path testFilePath = Paths.get("C:\\Users\\Username\\Desktop\\testFile.txt"); System.out.println(testFilePath.isAbsolute()); } }
Konsolenausgabe:
WAHR
-
Path normalize()
— „normalisiert“ den aktuellen Pfad und entfernt unnötige Elemente daraus. Sie wissen vielleicht, dass gängige Betriebssysteme bei der Angabe von Pfaden häufig „.“-Zeichen verwenden. („aktuelles Verzeichnis“) und „..“ (übergeordnetes Verzeichnis). Zum Beispiel: „ ./Pictures/dog.jpg “ bedeutet, dass es in dem Verzeichnis, in dem wir uns gerade befinden, einen Ordner „Bilder“ und darin eine Datei „dog.jpg“ gibt.Also. Wenn Ihr Programm einen Pfad hat, der „.“ verwendet.
normalize()
oder „..“ entfernt die Methode sie und erhält einen Pfad, der sie nicht enthält:import java.nio.file.Path; import java.nio.file.Paths; public class Main { public static void main(String[] args) { Path path5 = Paths.get("C:\\Users\\Java\\.\\examples"); System.out.println(path5.normalize()); Path path6 = Paths.get("C:\\Users\\Java\\..\\examples"); System.out.println(path6.normalize()); } }
Konsolenausgabe:
C:\Benutzer\Java\examples
C:\Benutzer\examples -
Path relativize()
– Berechnet den relativen Pfad zwischen dem aktuellen und dem übergebenen Pfad.Zum Beispiel:
import java.nio.file.Path; import java.nio.file.Paths; public class Main { public static void main(String[] args) { Path testFilePath1 = Paths.get("C:\\Users\\Users\\Users\\Users"); Path testFilePath2 = Paths.get("C:\\Users\\Users\\Users\\Users\\Username\\Desktop\\testFile.txt"); System.out.println(testFilePath1.relativize(testFilePath2)); } }
Konsolenausgabe:
Benutzername\Desktop\testFile.txt
Path
ist ziemlich umfangreich. Sie finden sie alle in der Oracle-Dokumentation . Wir werden mit der Überprüfung fortfahren Files
.
Dateien
Files
– Dies ist eine Dienstprogrammklasse, in die statische Methoden aus der Klasse verschoben wurden File
. Files
- Dies ist ungefähr das Gleiche wie Arrays
or Collections
, funktioniert nur mit Dateien und nicht mit Arrays und Sammlungen :) Der Schwerpunkt liegt auf der Verwaltung von Dateien und Verzeichnissen. Mit statischen Methoden Files
können wir Dateien und Verzeichnisse erstellen, löschen und verschieben. Für diese Operationen werden die Methoden createFile()
(für Verzeichnisse - createDirectory()
) move()
und verwendet delete()
. So verwenden Sie sie:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
public class Main {
public static void main(String[] args) throws IOException {
//Dateierstellung
Path testFile1 = Files.createFile(Paths.get("C:\\Users\\Username\\Desktop\\testFile111.txt"));
System.out.println(„Wurde die Datei erfolgreich erstellt?“);
System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testFile111.txt")));
// Verzeichnis erstellen
Path testDirectory = Files.createDirectory(Paths.get("C:\\Users\\Username\\Desktop\\testDirectory"));
System.out.println(„Wurde das Verzeichnis erfolgreich erstellt?“);
System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testDirectory")));
//Datei vom Desktop in das Testverzeichnis verschieben. Sie müssen mit dem Namen der Datei im Ordner verschieben!
testFile1 = Files.move(testFile1, Paths.get("C:\\Users\\Username\\Desktop\\testDirectory\\testFile111.txt"), REPLACE_EXISTING);
System.out.println(„Ist unsere Datei noch auf dem Desktop?“);
System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testFile111.txt")));
System.out.println(„Wurde unsere Datei in testDirectory verschoben?“);
System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testDirectory\\testFile111.txt")));
//Datei löschen
Files.delete(testFile1);
System.out.println(„Existiert die Datei noch?“);
System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testDirectory\\testFile111.txt")));
}
}
Hier erstellen wir zunächst eine Datei (Methode Files.createFile()
) auf dem Desktop und anschließend dort einen Ordner (Methode Files.createDirectory()
). Danach verschieben wir die Datei (Methode Files.move()
) vom Desktop in diesen neuen Ordner und löschen am Ende die Datei (Methode Files.delete()
). Konsolenausgabe: Wurde die Datei erfolgreich erstellt? true Wurde das Verzeichnis erfolgreich erstellt? true Befindet sich unsere Datei noch auf dem Desktop? false Wurde unsere Datei in testDirectory verschoben? true Existiert die Datei noch? FALSCH Passt auf:Path
Genau wie Schnittstellenmethoden geben viele Methoden Files
ein Objekt zurückPath
. Die meisten Klassenmethoden Files
akzeptieren auch Path
. Hier wird eine Methode zu Ihrem treuen Helfer Paths.get()
– nutzen Sie sie aktiv. Was ist sonst noch interessant Files
? Was der alten Klasse wirklich fehlte, war die ! File
-Methode. copy()
Wir haben zu Beginn des Vortrags über ihn gesprochen, jetzt ist es an der Zeit, ihn kennenzulernen!
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
public class Main {
public static void main(String[] args) throws IOException {
//Dateierstellung
Path testFile1 = Files.createFile(Paths.get("C:\\Users\\Username\\Desktop\\testFile111.txt"));
System.out.println(„Wurde die Datei erfolgreich erstellt?“);
System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testFile111.txt")));
// Verzeichnis erstellen
Path testDirectory2 = Files.createDirectory(Paths.get("C:\\Users\\Username\\Desktop\\testDirectory2"));
System.out.println(„Wurde das Verzeichnis erfolgreich erstellt?“);
System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testDirectory2")));
//kopiere die Datei vom Desktop in das Verzeichnis testDirectory2.
testFile1 = Files.copy(testFile1, Paths.get("C:\\Users\\Username\\Desktop\\testDirectory2\\testFile111.txt"), REPLACE_EXISTING);
System.out.println(„Ist unsere Datei noch auf dem Desktop?“);
System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testFile111.txt")));
System.out.println(„Wurde unsere Datei in testDirectory kopiert?“);
System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testDirectory2\\testFile111.txt")));
}
}
Konsolenausgabe: Wurde die Datei erfolgreich erstellt? true Wurde das Verzeichnis erfolgreich erstellt? true Befindet sich unsere Datei noch auf dem Desktop? true Wurde unsere Datei in testDirectory kopiert? true Jetzt können Sie Dateien programmgesteuert kopieren! :) Mit der Klasse Files
können Sie jedoch nicht nur die Dateien selbst verwalten, sondern auch mit deren Inhalten arbeiten. Um Daten in eine Datei zu schreiben, gibt es eine Methode write()
und zum Lesen sogar 3:, read()
und auf Letzteres werden readAllBytes()
wir im Detail eingehen. readAllLines()
Warum darauf? Weil es einen sehr interessanten Rückgabetyp hat - List<String>
! Das heißt, es gibt uns eine Liste der Zeilen in der Datei zurück. Das macht das Arbeiten mit den Inhalten natürlich sehr komfortabel, da die gesamte Datei beispielsweise Zeile für Zeile in einer regulären Schleife auf der Konsole ausgegeben werden kann for
:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import static java.nio.charset.StandardCharsets.UTF_8;
public class Main {
public static void main(String[] args) throws IOException {
List<String> lines = Files.readAllLines(Paths.get("C:\\Users\\Username\\Desktop\\pushkin.txt"), UTF_8);
for (String s: lines) {
System.out.println(s);
}
}
}
Konsolenausgabe: Ich erinnere mich an einen wunderbaren Moment: Du erschienst vor mir, wie eine flüchtige Vision, wie ein Genie von reiner Schönheit. Sehr bequem! :) Diese Funktion erschien in Java 7. In Java 8 erschien die Stream API , die Java einige Elemente der funktionalen Programmierung hinzufügte. Einschließlich umfangreicherer Funktionen für die Arbeit mit Dateien. Stellen Sie sich vor, wir haben eine Aufgabe: Finden Sie alle Zeilen in einer Datei, die mit dem Wort „How“ beginnen, konvertieren Sie sie in GROSSBUCHSTABEN und geben Sie sie auf der Konsole aus. Wie würde eine Lösung mit einer Klasse Files
in Java 7 aussehen? Etwas wie das:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import static java.nio.charset.StandardCharsets.UTF_8;
public class Main {
public static void main(String[] args) throws IOException {
List<String> lines = Files.readAllLines(Paths.get("C:\\Users\\Username\\Desktop\\pushkin.txt"), UTF_8);
List<String> result = new ArrayList<>();
for (String s: lines) {
if (s.startsWith("Wie")) {
String upper = s.toUpperCase();
result.add(upper);
}
}
for (String s: result) {
System.out.println(s);
}
}
}
Konsolenausgabe: WIE EINE FASTEN-VISION, WIE EIN GENIE VON REINER SCHÖNHEIT. Wir scheinen es geschafft zu haben, aber glauben Sie nicht, dass sich unser Code für eine so einfache Aufgabe als etwas ... ausführlich erwiesen hat? Mit der Java 8 Stream API sieht die Lösung deutlich eleganter aus:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) throws IOException {
Stream<String> stream = Files.lines(Paths.get("C:\\Users\\Username\\Desktop\\pushkin.txt"));
List<String> result = stream
.filter(line -> line.startsWith("Wie"))
.map(String::toUpperCase)
.collect(Collectors.toList());
result.forEach(System.out::println);
}
}
Wir haben das gleiche Ergebnis erzielt, aber mit viel weniger Code! Darüber hinaus kann man nicht sagen, dass wir an „Lesbarkeit“ verloren haben. Ich denke, Sie können leicht kommentieren, was dieser Code bewirkt, auch wenn Sie mit der Stream-API nicht vertraut sind. Aber kurz gesagt, ein Stream ist eine Folge von Elementen, für die Sie verschiedene Funktionen ausführen können. Wir erhalten das Stream-Objekt von der Methode Files.lines()
und wenden dann drei Funktionen darauf an:
-
Mit der Methode
filter()
wählen wir nur die Zeilen aus der Datei aus, die mit „How“ beginnen. -
Wir gehen alle ausgewählten Zeilen mit der Methode durch
map()
und reduzieren jede von ihnen auf GROSSBUCHSTABEN. -
Wir kombinieren alle resultierenden Zeilen mit
List
dercollect()
.
Files.walkFileTree()
. Folgendes müssen wir tun. Zuerst brauchen wir FileVisitor
. FileVisitor
ist eine spezielle Schnittstelle, die alle Methoden zum Durchlaufen des Dateibaums beschreibt. Konkret werden wir dort eine Logik einbauen, um den Inhalt der Datei zu lesen und zu prüfen, ob sie den von uns benötigten Text enthält. So wird unseres aussehen FileVisitor
:
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.List;
public class MyFileVisitor extends SimpleFileVisitor<Path> {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
List<String> lines = Files.readAllLines(file);
for (String s: lines) {
if (s.contains("This is the file we need")) {
System.out.println(„Erforderliche Datei gefunden!“);
System.out.println(file.toAbsolutePath());
break;
}
}
return FileVisitResult.CONTINUE;
}
}
In diesem Fall erbt unsere Klasse von SimpleFileVisitor
. Dies ist eine Klasse, die implementiert FileVisitor
, in der Sie nur eine Methode überschreiben müssen: visitFile()
. Hier beschreiben wir, was mit jeder Datei in jedem Verzeichnis getan werden muss. Wenn Sie eine komplexere Traversierungslogik benötigen, sollten Sie Ihre eigene Implementierung schreiben FileVisitor
. Dort müssen Sie drei weitere Methoden implementieren:
-
preVisitDirectory()
— Logik, die vor dem Betreten des Ordners ausgeführt werden muss; -
visitFileFailed()
— was zu tun ist, wenn die Eingabe der Datei nicht möglich ist (kein Zugriff oder aus anderen Gründen); -
postVisitDirectory()
— die Logik, die nach dem Betreten des Ordners ausgeführt werden muss.
SimpleFileVisitor
. Die Logik innerhalb der Methode visitFile()
ist recht einfach: Lesen Sie alle Zeilen aus der Datei, prüfen Sie, ob sie den benötigten Inhalt enthalten, und geben Sie in diesem Fall den absoluten Pfad zur Konsole aus. Die einzige Zeile, die Ihnen Probleme bereiten könnte, ist diese:
return FileVisitResult.CONTINUE;
Eigentlich ist alles einfach. Hier beschreiben wir lediglich, was das Programm tun soll, nachdem die Datei eingegeben und alle erforderlichen Vorgänge abgeschlossen sind. In unserem Fall müssen wir den Baum weiter durchqueren, also wählen wir die Option CONTINUE
. Aber wir könnten zum Beispiel eine andere Aufgabe haben: nicht alle Dateien zu finden, die „Dies ist die Datei, die wir brauchen“ enthalten, sondern nur eine solche Datei . Danach muss das Programm beendet werden. In diesem Fall würde unser Code genau gleich aussehen, aber statt break; würde:
return FileVisitResult.TERMINATE;
Nun, lassen Sie uns unseren Code ausführen und sehen, ob er funktioniert.
import java.io.IOException;
import java.nio.file.*;
public class Main {
public static void main(String[] args) throws IOException {
Files.walkFileTree(Paths.get("C:\\Users\\Username\\Desktop\\testFolder"), new MyFileVisitor());
}
}
Konsolenausgabe: Die benötigte Datei wurde gefunden! C:\Benutzer\Benutzername\Desktop\testFolder\FileWeNeed1.txt Die benötigte Datei wurde gefunden! C:\Benutzer\Benutzername\Desktop\testFolder\level1-a\level2-aa\FileWeNeed2.txt Die benötigte Datei wurde gefunden! C:\Benutzer\Benutzername\Desktop\testFolder\level1-b\level2-bb\FileWeNeed3.txt Großartig, wir haben es geschafft! :) Wenn du mehr darüber erfahren möchtest walkFileTree()
, empfehle ich dir diesen Artikel . Sie können auch eine kleine Aufgabe erledigen – sie SimpleFileVisitor
durch eine normale ersetzen FileVisitor
, alle vier Methoden implementieren und einen Zweck für dieses Programm festlegen. Sie können beispielsweise ein Programm schreiben, das alle Ihre Aktionen protokolliert: den Namen einer Datei oder eines Ordners in der Konsole vor/nach der Eingabe anzeigen. Das ist alles – bis später! :) :)
GO TO FULL VERSION