Laluan
Paths ialah kelas yang sangat mudah dengan satu kaedah statik: get() . Ia dicipta semata-mata untuk mendapatkan objek Path daripada rentetan atau URI yang diluluskan. Ia tidak mempunyai fungsi lain. Berikut ialah contoh di tempat kerja:
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");
}
}
Bukan kelas yang paling kompleks, bukan? :) Nah, kami juga mempunyai jenis Laluan ini . Mari kita ketahui apa itu Path dan mengapa ia diperlukan :)
Laluan
Path , pada umumnya, ialah analog yang direka bentuk semula bagi kelas Fail . Ia lebih mudah untuk digunakan daripada File . Pertama , banyak kaedah utiliti (statik) telah dikeluarkan dan dipindahkan ke kelas Fail . Kedua , perintah telah dikenakan ke atas nilai pulangan kaedah antara muka Laluan . Dalam kelas Fail , kaedah mengembalikan sama ada String , atau boolean , atau File . Ia tidak mudah untuk memikirkannya. Sebagai contoh, terdapat kaedah getParent() yang mengembalikan rentetan yang mewakili laluan induk fail semasa. Tetapi terdapat juga akaedah getParentFile() , yang mengembalikan perkara yang sama tetapi dalam bentuk objek Fail ! Ini jelas berlebihan. Oleh itu, dalam antara muka Path , kaedah getParent() dan kaedah lain untuk bekerja dengan fail hanya mengembalikan objek Path . Tiada timbunan pilihan — semuanya mudah dan ringkas. Apakah beberapa kaedah berguna yang ada pada Path ? Berikut ialah beberapa daripada mereka dan contoh cara mereka berfungsi:-
getFileName() : mengembalikan nama fail daripada laluan;
-
getParent() : mengembalikan direktori "ibu bapa" laluan semasa (dengan kata lain, direktori yang terletak betul-betul di atas dalam pepohon direktori);
-
getRoot() : mengembalikan direktori "root", iaitu direktori di bahagian atas pokok direktori;
-
startsWith() , endsWith() : semak sama ada laluan bermula/berakhir dengan laluan yang diluluskan:
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); } }
Output konsol:
testFile.txt C:\Users\Username\Desktop C:\ true false
Beri perhatian kepada cara kaedah endsWith() berfungsi. Ia menyemak sama ada laluan semasa berakhir dengan laluan yang diluluskan . Khususnya, sama ada ia berada dalam laluan , bukan dalam rentetan yang diluluskan .
Bandingkan keputusan kedua-dua panggilan ini:
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")); } }
Output konsol:
false true
Kaedah endsWith() mesti lulus laluan tulen, bukan hanya satu set aksara: jika tidak, hasilnya akan sentiasa palsu, walaupun laluan semasa benar-benar berakhir dengan jujukan aksara itu (seperti yang berlaku dengan "estFile.txt "dalam contoh di atas).
Selain itu, Path mempunyai sekumpulan kaedah yang memudahkan kerja dengan laluan mutlak (penuh) dan relatif .
-
boolean isAbsolute() mengembalikan benar jika laluan semasa adalah mutlak:
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()); } }
Output konsol:
true
-
Path normalize() : "menormalkan" laluan semasa, mengalih keluar elemen yang tidak perlu daripadanya. Anda mungkin tahu bahawa dalam sistem pengendalian popular simbol "." (direktori semasa) dan ".." (direktori induk) sering digunakan untuk menetapkan laluan. Contohnya, " ./Pictures/dog.jpg " bermaksud direktori semasa mempunyai folder "Pictures", yang seterusnya mengandungi fail "dog.jpg".
Tengok sini. Jika laluan menggunakan "." atau ".." muncul dalam program anda, kaedah normalize() akan mengalih keluarnya dan menghasilkan laluan yang tidak mengandunginya:
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()); } }
Output konsol:
C:\Users\Java\examples C:\Users\examples
-
Path relativize() : mengira laluan relatif antara laluan semasa dan laluan yang dilalui.
Sebagai contoh:
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)); } }
Output konsol:
Username\Desktop\testFile.txt
Fail
Fail ialah kelas utiliti yang memegang kaedah statik yang diambil daripada kelas Fail . Fail adalah setanding dengan Tatasusunan atau Koleksi . Perbezaannya ialah ia berfungsi dengan fail, bukan tatasusunan atau koleksi :) Ia memberi tumpuan kepada mengurus fail dan direktori. Menggunakan kaedah statik kelas Fail , kami boleh mencipta, memadam dan memindahkan fail dan direktori. Operasi ini dilakukan menggunakankaedah createFile() (untuk direktori, createDirectory() ), move() dan delete() . Begini cara menggunakannya:
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")));
}
}
Di sini kita mula-mula mencipta fail ( kaedah Files.createFile() pada desktop. Kemudian kami mencipta folder di lokasi yang sama ( kaedah Files.createDirectory() ). Selepas itu, kami mengalihkan fail ( kaedah Files.move() dari desktop ke folder baharu ini, dan akhirnya kami memadamkan fail ( kaedah Files.delete() ). Output konsol:
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
Catatan:seperti kaedah antara Path
muka, banyak kaedah kelas Files
mengembalikanPath
objek. Kebanyakan kaedah kelas Files
juga mengambil Path
objek sebagai input. Di sini kaedah itu Paths.get()
akan menjadi pembantu setia anda — gunakannya dengan sebaiknya. Apa lagi yang menarik Files
? File
Apa yang sebenarnya kekurangan kelas lama ialah copy()
kaedah! Kami bercakap mengenainya pada permulaan pelajaran ini. Kini tiba masanya untuk bertemu dengannya!
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")));
}
}
Output konsol:
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
Sekarang anda tahu cara menyalin fail secara pemrograman! :) Sudah tentu, Files
kelas itu membolehkan anda bukan sahaja mengurus fail itu sendiri, tetapi juga berfungsi dengan kandungannya. Ia mempunyai write()
kaedah untuk menulis data ke fail, dan kesemua 3 kaedah untuk membaca data: read()
, readAllBytes()
, dan readAllLines()
Kami akan membincangkan secara terperinci tentang yang terakhir. Kenapa yang itu? Kerana ia mempunyai jenis pulangan yang sangat menarik: List<String>
! Iaitu, ia mengembalikan kita senarai semua baris dalam fail. Sudah tentu, ini menjadikannya sangat mudah untuk bekerja dengan kandungan fail, kerana keseluruhan fail, baris demi baris, boleh, sebagai contoh, dipaparkan pada konsol menggunakan gelung biasa 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);
}
}
}
Output konsol:
I still recall the wondrous moment:
When you appeared before my sight,
As though a brief and fleeting omen,
Pure phantom in enchanting light.
Sangat mudah! :) Keupayaan ini muncul dalam Java 7. Stream API muncul dalam Java 8. Ia menambahkan beberapa elemen pengaturcaraan berfungsi pada Java. Termasuk keupayaan pengendalian fail yang lebih kaya. Bayangkan kita mempunyai tugas berikut: cari semua baris yang bermula dengan perkataan "As", tukarkannya kepada HURUF BESAR, dan paparkannya pada konsol. Apakah rupa penyelesaian menggunakan Files
kelas dalam Java 7? Sesuatu seperti ini:
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);
}
}
}
Output konsol:
AS THOUGH A BRIEF AND FLEETING OMEN,
PURE PHANTOM IN ENCHANTING LIGHT.
Misi tercapai, tetapi tidakkah anda berfikir bahawa untuk tugas yang begitu mudah, kod kami ternyata sedikit... verbose? Menggunakan API Stream Java 8, penyelesaiannya kelihatan lebih elegan:
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);
}
}
Kami mencapai hasil yang sama, tetapi dengan lebih sedikit kod! Apatah lagi, tiada siapa yang boleh mengatakan bahawa kita telah kehilangan "kebolehbacaan". Saya rasa anda boleh mengulas dengan mudah tentang perkara yang dilakukan oleh kod ini, walaupun tanpa mengetahui API Strim. Ringkasnya, Strim ialah jujukan elemen, di mana anda boleh melakukan pelbagai operasi. Kami mendapat objek Stream daripada Files.lines()
kaedah, dan kemudian menggunakan 3 fungsi padanya:
-
Kami menggunakan
filter()
kaedah untuk memilih hanya baris tersebut daripada fail yang bermula dengan "As". -
Kami berjalan melalui semua baris yang dipilih menggunakan
map()
kaedah dan menukar setiap baris kepada HURUF BESAR. -
Kami menggunakan
collect()
kaedah untuk mengumpulkan semua baris yang diterima ke dalamList
.
AS THOUGH A BRIEF AND FLEETING OMEN,
PURE PHANTOM IN ENCHANTING LIGHT.
Sekarang mari kita kembali kepada roti dan mentega kita, iaitu fail :) Keupayaan terakhir yang akan kita pertimbangkan hari ini ialah berjalan melalui pokok fail . Dalam sistem pengendalian moden, struktur fail paling kerap kelihatan seperti pokok: ia mempunyai akar dan terdapat cawangan, yang boleh mempunyai cawangan lain, dll. Akar dan cawangan adalah direktori. Sebagai contoh, direktori " С:// " mungkin akarnya. Ia termasuk dua cawangan: " C://Downloads " dan " C://Users ". Setiap cawangan ini mempunyai dua cawangan: " C://Downloads/Pictures ", " C://Downloads/Video ", " C://Users/JohnSmith ", " C://Users/Pudge2005". Dan cawangan ini pula mempunyai cawangan lain, dsb. dan inilah sebabnya kami memanggilnya pokok. Di Linux, strukturnya serupa, tetapi direktori / adalah akarnya. Sekarang bayangkan





Files.walkFileTree ()
. Inilah yang perlu kita lakukan. Pertama, kita memerlukan FileVisitor
. FileVisitor
ialah antara muka khas, di mana kaedah untuk melintasi pokok fail diterangkan. Khususnya, di situlah kita akan meletakkan logik untuk membaca kandungan fail dan menyemak sama ada ia mengandungi teks yang kita perlukan. Inilah FileVisitor
rupa kami:
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;
}
}
Dalam kes ini, kelas kami mewarisi SimpleFileVisitor
. Ini ialah kelas yang melaksanakan FileVisitor
, di mana kita perlu mengatasi hanya satu kaedah: visitFile()
. Di sini kami menentukan perkara yang perlu dilakukan dengan setiap fail dalam setiap direktori. Jika anda memerlukan logik yang lebih kompleks untuk melintasi struktur fail, anda harus menulis pelaksanaan anda sendiri FileVisitor
. Anda perlu melaksanakan 3 lagi kaedah dalam kelas itu:
-
preVisitDirectory()
: logik untuk dilaksanakan sebelum memasuki folder; -
visitFileFailed()
: logik untuk dilaksanakan jika fail tidak boleh dilawati (tiada akses, atau atas sebab lain); -
postVisitDirectory()
: logik untuk dilaksanakan selepas memasuki folder.
SimpleFileVisitor
. Logik di dalam visitFile()
kaedah ini agak mudah: baca semua baris dalam fail, semak sama ada ia mengandungi kandungan yang kami perlukan, dan jika ya, cetak laluan mutlak pada konsol. Satu-satunya baris yang mungkin menyebabkan anda kesukaran ialah yang ini:
return FileVisitResult.CONTINUE;
Sebenarnya, ini sangat mudah. Di sini kami hanya menerangkan perkara yang perlu dilakukan oleh program selepas fail dilawati dan semua operasi yang diperlukan telah dilakukan. Dalam kes kami, kami mahu terus melintasi pokok itu, jadi kami memilih CONTINUE
pilihan. Tetapi, sebagai alternatif, kami mungkin mempunyai objektif yang berbeza: daripada mencari semua fail yang mengandungi "Ini ialah fail yang kami perlukan", cari hanya satu fail sedemikian . Selepas itu, program harus ditamatkan. Dalam kes ini, kod kami akan kelihatan sama, tetapi bukannya pecah akan ada:
return FileVisitResult.TERMINATE;
Baiklah, mari jalankan kod kami dan lihat sama ada ia berfungsi.
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());
}
}
Output konsol:
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
Cemerlang! Ianya berhasil! :) Anda juga boleh menerima cabaran kecil ini: gantikan SimpleFileVisitor
dengan yang biasa FileVisitor
, ganti semua 4 kaedah dan tentukan tujuan anda sendiri untuk program ini. Sebagai contoh, anda boleh menulis program yang merekodkan semua tindakannya: paparkan nama fail atau folder sebelum atau selepas memasukkannya. Itu sahaja buat masa ini. Jumpa lagi! :)
GO TO FULL VERSION