Ösvények
A Paths egy nagyon egyszerű osztály egyetlen statikus metódussal: get() . Kizárólag azért jött létre, hogy az átadott karakterláncból vagy URI-ból Path objektumot kapjon. Nincs más funkciója. Íme egy példa a munkahelyen:
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");
}
}
Nem a legösszetettebb osztály, igaz? :) Nos, nálunk is megvan ez a Path típus. Találjuk ki, mi az a Path és miért van rá szükség :)
Pálya
A Path nagyjából a File osztály újratervezett analógja. Sokkal könnyebb vele dolgozni, mint a File -al . Először sok segédprogram (statikus) metódust vettek ki és helyeztek át a Fájlok osztályba. Másodszor , a Path interfész metódusainak visszatérési értékei sorrendbe kerültek . A Fájl osztályban a metódusok karakterláncot , logikai értéket vagy fájlt adtak vissza . Nem volt könnyű rájönni. Például volt egy getParent() metódus, amely az aktuális fájl szülőútvonalát képviselő karakterláncot adott vissza. De volt még agetParentFile() metódus, amely ugyanazt adta vissza, de File objektum formájában! Ez egyértelműen felesleges. Ennek megfelelően a Path felületen a getParent() metódus és a fájlokkal való munkavégzés egyéb metódusai egyszerűen egy Path objektumot adnak vissza. Nincs halom lehetőség – minden könnyű és egyszerű. Melyek a Path hasznos módszerei ? Íme néhány közülük, és példák a működésükre:-
getFileName() : visszaadja a fájlnevet az elérési útból;
-
getParent() : az aktuális elérési út "szülő" könyvtárát adja vissza (más szóval a könyvtárfában közvetlenül fent található könyvtárat);
-
getRoot() : a "root" könyvtárat adja vissza, azaz a könyvtárfa tetején lévő könyvtárat;
-
startsWith() , endsWith() : ellenőrizze, hogy az elérési út az átadott útvonallal kezdődik-e/végeződik-e:
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); } }
Konzol kimenet:
testFile.txt C:\Users\Username\Desktop C:\ true false
Ügyeljen az endsWith() metódus működésére. Ellenőrzi, hogy az aktuális útvonal véget ér-e az átadott útvonallal . Pontosabban, hogy az elérési útban van-e , és nem az átadott karakterláncban .
Hasonlítsa össze a két hívás eredményét:
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")); } }
Konzol kimenet:
false true
Az endsWith() metódusnak valódi elérési utat kell átadni, nem csak karakterkészletet: ellenkező esetben az eredmény mindig hamis lesz, még akkor is, ha az aktuális elérési út valóban ezzel a karaktersorozattal végződik (mint az "estFile.txt" esetében " a fenti példában).
Ezen túlmenően, a Path rendelkezik egy olyan módszercsoporttal, amely leegyszerűsíti az abszolút (teljes) és relatív útvonalakkal való munkát .
-
A logikai isAbsolute() igazat ad vissza, ha az aktuális elérési út abszolút:
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()); } }
Konzol kimenet:
true
-
Path normalize() : "normalizálja" az aktuális útvonalat, eltávolítja belőle a felesleges elemeket. Talán tudja, hogy a népszerű operációs rendszerekben a "." (aktuális könyvtár) és ".." (szülőkönyvtár) gyakran használják az elérési utak kijelölésére. Például a " ./Pictures/dog.jpg " azt jelenti, hogy az aktuális könyvtárban van egy "Pictures" mappa, amely viszont egy "kutya.jpg" fájlt tartalmaz.
Nézz ide. Ha egy elérési út a "." vagy ".." jelenik meg a programban, a normalize() metódus eltávolítja őket, és létrehoz egy olyan elérési utat, amely nem tartalmazza őket:
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()); } }
Konzol kimenet:
C:\Users\Java\examples C:\Users\examples
-
Path relativize() : kiszámítja a relatív utat az aktuális és az átadott út között.
Például:
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)); } }
Konzol kimenet:
Username\Desktop\testFile.txt
Fájlok
A Files egy segédprogramosztály, amely a Fájl osztályból kivett statikus metódusokat tartalmazza. A Files hasonló a tömbökhöz vagy a gyűjteményekhez . A különbség az, hogy fájlokkal működik, nem tömbökkel vagy gyűjteményekkel :) A fájlok és könyvtárak kezelésére koncentrál. A Fájlok osztály statikus metódusai segítségével fájlokat és könyvtárakat hozhatunk létre, törölhetünk, mozgathatunk. Ezeket a műveleteket a createFile() (könyvtárak esetén createDirectory() ), move() és delete() metódusokkalhajtjuk végreA következőképpen használhatja őket:
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 {
// Create a file
Path testFile1 = Files.createFile(Paths.get("C:\\Users\\Username\\Desktop\\testFile111.txt"));
System.out.println("Was the file created successfully?");
System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testFile111.txt")));
// Create a directory
Path testDirectory = Files.createDirectory(Paths.get("C:\\Users\\Username\\Desktop\\testDirectory"));
System.out.println("Was the directory created successfully?");
System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testDirectory")));
// Move the file from the desktop to the testDirectory directory. When you move a folder, you need to indicate its name in the folder!
testFile1 = Files.move(testFile1, Paths.get("C:\\Users\\Username\\Desktop\\testDirectory\\testFile111.txt"), REPLACE_EXISTING);
System.out.println("Did our file remain on the desktop?");
System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testFile111.txt")));
System.out.println("Has our file been moved to testDirectory?");
System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testDirectory\\testFile111.txt")));
// Delete a file
Files.delete(testFile1);
System.out.println("Does the file still exist?");
System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testDirectory\\testFile111.txt")));
}
}
Itt először létrehozunk egy fájlt ( Files.createFile() metódus) az asztalon. Ezután létrehozunk egy mappát ugyanazon a helyen ( Files.createDirectory() metódus). Ezt követően áthelyezzük a fájlt ( Files.move() metódus) az asztalról ebbe az új mappába, végül töröljük a fájlt ( Files.delete() metódus). Konzol kimenet:
Was the file created successfully?
true
Was the directory created successfully?
true
Did our file remain on the desktop?
false
Has our file been moved to testDirectory?
true
Does the file still exist?
false
Jegyzet:Path
az interfész metódusaihoz hasonlóan az osztály számos metódusa is objektumot Files
ad visszaPath
. Az osztály legtöbb metódusa objektumokat Files
is Path
bemenetként vesz fel. Itt a Paths.get()
módszer az Ön hűséges asszisztense lesz – használja ki jól. Mi az érdekes még Files
? Ami a régi File
osztályból nagyon hiányzott, az egy copy()
módszer! A lecke elején beszéltünk róla. Itt az ideje, hogy találkozzunk vele!
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 {
// Create a file
Path testFile1 = Files.createFile(Paths.get("C:\\Users\\Username\\Desktop\\testFile111.txt"));
System.out.println("Was the file created successfully?");
System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testFile111.txt")));
// Create a directory
Path testDirectory2 = Files.createDirectory(Paths.get("C:\\Users\\Username\\Desktop\\testDirectory2"));
System.out.println("Was the directory created successfully?");
System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testDirectory2")));
// Copy the file from the desktop to the testDirectory2 directory.
testFile1 = Files.copy(testFile1, Paths.get("C:\\Users\\Username\\Desktop\\testDirectory2\\testFile111.txt"), REPLACE_EXISTING);
System.out.println("Did our file remain on the desktop?");
System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testFile111.txt")));
System.out.println("Was our file copied to testDirectory?");
System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testDirectory2\\testFile111.txt")));
}
}
Konzol kimenet:
Was the file created successfully?
true
Was the directory created successfully?
true
Did our file remain on the desktop?
true
Was our file copied to testDirectory?
true
Most már tudja, hogyan másolhat fájlokat programozottan! :) Természetesen az Files
osztályban nem csak magát a fájlt kezelhetjük, hanem a tartalmával is dolgozhatunk. Rendelkezik az write()
adatok fájlba írásának módszerével, és mind a 3 módszerrel az adatok beolvasására: read()
, readAllBytes()
, és readAllLines()
Az utolsónál részletesen kitérünk. Miért pont az? Mert nagyon érdekes visszatérési típusa van: List<String>
! Azaz visszaadja nekünk a fájl összes sorának listáját. Ez természetesen nagyon kényelmessé teszi a fájltartalommal való munkát, mert a teljes fájl soronként megjeleníthető például a konzolon egy közönséges for
ciklus segítségével:
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);
}
}
}
Konzol kimenet:
I still recall the wondrous moment:
When you appeared before my sight,
As though a brief and fleeting omen,
Pure phantom in enchanting light.
Szuper kényelmes! :) Ez a képesség a Java 7-ben jelent meg. A Stream API a Java 8-ban jelent meg. A funkcionális programozás néhány elemét hozzáadja a Java-hoz. Gazdagabb fájlkezelési képességekkel. Képzeljük el, hogy a következő feladatunk van: keressük meg az „As” szóval kezdődő összes sort, alakítsuk NAGYBETŐSRE, és jelenítsük meg a konzolon. Hogyan nézne ki az osztályt használó megoldás Files
Java 7-ben? Valami ilyesmi:
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("As")) {
String upper = s.toUpperCase();
result.add(upper);
}
}
for (String s: result) {
System.out.println(s);
}
}
}
Konzol kimenet:
AS THOUGH A BRIEF AND FLEETING OMEN,
PURE PHANTOM IN ENCHANTING LIGHT.
A küldetés teljesítve, de nem gondolja, hogy egy ilyen egyszerű feladathoz a kódunk kicsit... bőbeszédűnek bizonyult? A Java 8 Stream API-ját használva a megoldás sokkal elegánsabbnak tűnik:
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("As"))
.map(String::toUpperCase)
.collect(Collectors.toList());
result.forEach(System.out::println);
}
}
Ugyanazt az eredményt értük el, de sokkal kevesebb kóddal! Ráadásul senki sem mondhatja, hogy elveszítettük az „olvashatóságot”. Azt hiszem, könnyen kommentálhatja, mit csinál ez a kód, még akkor is, ha nem ismeri a Stream API-t. Röviden, a Stream olyan elemek sorozata, amelyeken keresztül különféle műveleteket hajthat végre. A metódusból egy Stream objektumot kapunk Files.lines()
, majd 3 függvényt alkalmazunk rá:
-
A
filter()
módszerrel csak azokat a sorokat jelöljük ki a fájlból, amelyek "As"-vel kezdődnek. -
A metódussal végigjárjuk az összes kiválasztott sort
map()
, és mindegyiket NAGYBETŰRE alakítjuk. -
A módszert arra használjuk,
collect()
hogy az összes kapott sort egyList
.
AS THOUGH A BRIEF AND FLEETING OMEN,
PURE PHANTOM IN ENCHANTING LIGHT.
Most térjünk vissza a kenyerünkhöz, vagyis a fájlokhoz :) Az utolsó lehetőség, amit ma figyelembe veszünk, a reszelőfán való séta . A modern operációs rendszerekben a fájlstruktúra leggyakrabban fának tűnik: van gyökér, és vannak ágak, amelyeknek lehetnek más ágai stb. A gyökér és az ágak könyvtárak. Például a " С:// " könyvtár lehet a gyökér. Két ágat tartalmaz: " C://Downloads " és " C://Users ". Mindegyik ágnak két ága van: " C://Downloads/Pictures ", " C://Downloads/Video ", " C://Users/JohnSmith ", " C://Users/Pudge2005"". És ezeknek az ágaknak vannak más ágai stb. és ezért hívjuk fának. Linuxon a szerkezet hasonló, de a / könyvtár 





Files.walkFileTree ()
. Íme, mit kell tennünk. Először is szükségünk van egy FileVisitor
. FileVisitor
egy speciális interfész, amelyen a fájlfa bejárásának módszerei vannak leírva. Konkrétan ide tesszük a fájl tartalmának beolvasásának logikáját és annak ellenőrzését, hogy az tartalmazza-e a szükséges szöveget. Nálunk így FileVisitor
néz ki:
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("We found a file we need!");
System.out.println(file.toAbsolutePath());
break;
}
}
return FileVisitResult.CONTINUE;
}
}
Ebben az esetben az osztályunk örökli SimpleFileVisitor
. Ez egy olyan osztály, amely megvalósítja a -t FileVisitor
, amelyben csak egy metódust kell felülbírálnunk: visitFile()
. Itt meghatározzuk, hogy mit kell tenni az egyes könyvtárakban található fájlokkal. Ha bonyolultabb logikára van szüksége a fájlstruktúra bejárásához, akkor meg kell írnia a saját implementációját FileVisitor
. Ebben az osztályban további 3 metódust kell megvalósítania:
-
preVisitDirectory()
: a mappa belépés előtt végrehajtandó logika; -
visitFileFailed()
: a végrehajtandó logika, ha egy fájl nem látogatható (nincs hozzáférés, vagy egyéb okok miatt); -
postVisitDirectory()
: a mappa beírása után végrehajtandó logika.
SimpleFileVisitor
. A visitFile()
metóduson belüli logika meglehetősen egyszerű: olvassuk el a fájl összes sorát, ellenőrizzük, hogy tartalmazzák-e a számunkra szükséges tartalmat, és ha igen, nyomtassuk ki az abszolút elérési utat a konzolon. Az egyetlen sor, amely nehézséget okozhat, ez:
return FileVisitResult.CONTINUE;
Valójában ez nagyon egyszerű. Itt egyszerűen leírjuk, mit kell tennie a programnak a fájl meglátogatása és az összes szükséges művelet elvégzése után. Esetünkben szeretnénk folytatni a fán való bejárást, ezért a CONTINUE
lehetőséget választjuk. Másik megoldásként azonban más célunk is lehet: ahelyett, hogy megkeressük az összes olyan fájlt, amely tartalmazza az "Ez az a fájl, amire szükségünk van", csak egy ilyen fájlt keressen . Ezt követően a programnak le kell állnia. Ebben az esetben a kódunk pontosan ugyanúgy nézne ki, de a break helyett a következő lenne:
return FileVisitResult.TERMINATE;
Nos, futtassuk le a kódunkat, és nézzük meg, működik-e.
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());
}
}
Konzol kimenet:
We found a file we need!
C:\Users\Username\Desktop\testFolder\FileWeNeed1.txt
We found a file we need!
C:\Users\Username\Desktop\testFolder\level1-a\level2-a-a\FileWeNeed2.txt
We found a file we need!
C:\Users\Username\Desktop\testFolder\level1-b\level2-b-b\FileWeNeed3.txt
Kiváló! Működött! :) Elfogadhatod ezt a kis kihívást is: cseréld le SimpleFileVisitor
egy közönséges -re FileVisitor
, írd felül mind a 4 módszert, és találd ki a saját célodat a programhoz. Például írhat egy programot, amely minden műveletét naplózza: megjeleníti a fájl vagy mappa nevét a beírás előtt vagy után. Ez minden most. Hamarosan találkozunk! :)
GO TO FULL VERSION