File
. Anda dapat membaca tentang karyanya di sini . Namun di Java 7, pembuat bahasa memutuskan untuk mengubah cara mereka bekerja dengan file dan direktori. Hal ini disebabkan oleh fakta bahwa kelas tersebut File
memiliki sejumlah kelemahan. Misalnya, tidak ada metode copy()
yang memungkinkan Anda menyalin file dari satu lokasi ke lokasi lain (fitur yang tampaknya jelas dibutuhkan). Selain itu, kelas tersebut File
memiliki cukup banyak metode yang mengembalikan boolean
nilai -. Jika kesalahan terjadi, metode seperti itu mengembalikan nilai false daripada memberikan pengecualian, sehingga membuat diagnosis kesalahan dan menentukan penyebabnya menjadi sangat sulit. Alih-alih satu kelas, File
muncul sebanyak 3 kelas: Paths
, Path
dan Files
. Tepatnya, Path
ini adalah antarmuka, bukan kelas. Mari kita cari tahu perbedaannya satu sama lain dan mengapa masing-masing diperlukan. Mari kita mulai dengan hal yang paling mudah - Paths
.
jalan
Paths
adalah kelas yang sangat sederhana dengan satu metode statis get()
. Itu dibuat semata-mata untuk mendapatkan objek bertipe dari string atau URI yang diteruskan Path
. Ia tidak memiliki fungsi lain. Berikut ini contoh karyanya:
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 sulit, bukan? :) Nah, karena kita punya objek bertipe Path
, mari kita cari tahu apa itu Path
dan mengapa itu diperlukan :)
Jalur
Path
, pada umumnya, adalah analog yang didesain ulang dari File
. Jauh lebih mudah untuk bekerja dengannya dibandingkan dengan File
. Pertama , banyak metode utilitas (statis) dihapus darinya dan dipindahkan ke kelas Files
. Kedua , Path
nilai kembalian dari metode diurutkan. Di kelas, File
metode mengembalikan this String
, that boolean
, that File
- tidak mudah untuk diketahui. Misalnya, ada metode getParent()
yang mengembalikan jalur induk untuk file saat ini sebagai string. Tetapi pada saat yang sama ada metode getParentFile()
yang mengembalikan hal yang sama, tetapi dalam bentuk objek File
! Hal ini jelas berlebihan. Oleh karena itu, dalam antarmuka, Path
metode getParent()
dan metode lain untuk bekerja dengan file cukup mengembalikan sebuah objek Path
. Tidak ada banyak pilihan - semuanya mudah dan sederhana. Metode berguna apa yang dimilikinya Path
? Berikut beberapa di antaranya dan contoh karyanya:
-
getFileName()
— mengembalikan nama file dari jalur; -
getParent()
— mengembalikan direktori “induk” sehubungan dengan jalur saat ini (yaitu, direktori yang lebih tinggi pada pohon direktori); -
getRoot()
— mengembalikan direktori “root”; yaitu yang ada di bagian atas pohon direktori; -
startsWith()
,endsWith()
— periksa apakah jalur dimulai/diakhiri dengan jalur yang dilewati: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); } }
Keluaran konsol:
testFile.txt
C:\Users\Nama Pengguna\Desktop
C:\
benar
salahPerhatikan cara kerja metode ini
endsWith()
. Ia memeriksa apakah jalur saat ini berakhir dengan jalur yang dilewati . Itu ada di jalurnya , dan bukan di kumpulan karakternya .Bandingkan hasil dari 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")); } }
Keluaran konsol:
salah
benarAnda harus meneruskan jalur lengkap ke metode tersebut
endsWith()
, dan bukan hanya sekumpulan karakter: jika tidak, hasilnya akan selalu salah , meskipun jalur saat ini benar-benar diakhiri dengan rangkaian karakter tersebut (seperti dalam kasus “estFile.txt ” pada contoh di atas).Selain itu, ada
Path
sekelompok metode yang menyederhanakan pekerjaan dengan jalur absolut (penuh) dan relatif .
-
boolean isAbsolute()
— mengembalikan nilai benar jika jalur saat ini absolut: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()); } }
Keluaran konsol:
BENAR
-
Path normalize()
— “menormalkan” jalur saat ini, menghapus elemen yang tidak perlu darinya. Anda mungkin tahu bahwa sistem operasi populer sering menggunakan karakter “.” saat menunjukkan jalur. (“direktori saat ini”) dan “..” (direktori induk). Misal : “ ./Pictures/dog.jpg ” artinya di direktori tempat kita berada sekarang terdapat folder Pictures dan didalamnya terdapat file “dog.jpg”Jadi begini. Jika program Anda memiliki jalur yang menggunakan “.” atau “..”, metode ini
normalize()
akan menghapusnya dan mendapatkan jalur yang tidak memuatnya: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()); } }
Keluaran konsol:
C:\Users\Java\example
C:\Users\example -
Path relativize()
— menghitung jalur relatif antara jalur saat ini dan jalur yang dilewati.Misalnya:
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)); } }
Keluaran konsol:
Nama pengguna\Desktop\testFile.txt
Path
cukup panjang. Anda dapat menemukan semuanya di dokumentasi Oracle . Kami akan melanjutkan ke peninjauan Files
.
File
Files
- ini adalah kelas utilitas tempat metode statis dari kelas tersebut dipindahkan File
. Files
- ini kira-kira sama dengan Arrays
or Collections
, hanya saja ini berfungsi dengan file, dan bukan dengan array dan koleksi :) Ini berfokus pada pengelolaan file dan direktori. Dengan menggunakan metode statis Files
, kita dapat membuat, menghapus, dan memindahkan file dan direktori. Untuk operasi ini metode yang digunakan createFile()
(untuk direktori - createDirectory()
), move()
dan delete()
. Berikut 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 {
//file creation
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 directory
Path testDirectory = Files.createDirectory(Paths.get("C:\\Users\\Username\\Desktop\\testDirectory"));
System.out.println("Was the directory successfully created?");
System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testDirectory")));
//move file from desktop to testDirectory. You need to move with the name of the file in the folder!
testFile1 = Files.move(testFile1, Paths.get("C:\\Users\\Username\\Desktop\\testDirectory\\testFile111.txt"), REPLACE_EXISTING);
System.out.println("Is our file left 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")));
//remove 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")));
}
}
Disini kita buat dulu file (method Files.createFile()
) di desktop, lalu buat folder disana (method Files.createDirectory()
). Setelah itu kita pindahkan file (method Files.move()
) dari desktop ke folder baru ini, dan terakhir kita hapus file (method Files.delete()
). Output konsol: Apakah file berhasil dibuat? benar Apakah direktori berhasil dibuat? benar Apakah file kita masih ada di desktop? false Apakah file kita sudah dipindahkan ke testDirectory? benar Apakah filenya masih ada? PALSU Perhatian:Sama seperti metode antarmuka Path
, banyak metode Files
mengembalikan objekPath
. Kebanyakan metode kelas Files
juga menerima Path
. Di sini suatu metode akan menjadi asisten setia Anda Paths.get()
- gunakan secara aktif. Apa lagi yang menarik Files
? Apa yang sebenarnya tidak dimiliki oleh kelas lama adalah metode ! File
. copy()
Kita sudah membicarakannya di awal perkuliahan, sekaranglah waktunya 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 {
//file creation
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 directory
Path testDirectory2 = Files.createDirectory(Paths.get("C:\\Users\\Username\\Desktop\\testDirectory2"));
System.out.println("Was the directory successfully created?");
System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testDirectory2")));
//copy the file from the desktop to the directory testDirectory2.
testFile1 = Files.copy(testFile1, Paths.get("C:\\Users\\Username\\Desktop\\testDirectory2\\testFile111.txt"), REPLACE_EXISTING);
System.out.println("Is our file left on the desktop?");
System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testFile111.txt")));
System.out.println("Has our file been copied to testDirectory?");
System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testDirectory2\\testFile111.txt")));
}
}
Output konsol: Apakah file berhasil dibuat? benar Apakah direktori berhasil dibuat? benar Apakah file kita masih ada di desktop? benar Apakah file kita disalin ke testDirectory? true Sekarang Anda dapat menyalin file secara terprogram! :) Namun kelas ini Files
memungkinkan Anda tidak hanya mengelola file itu sendiri, tetapi juga bekerja dengan isinya. Untuk menulis data ke suatu file, ia memiliki metode write()
, dan untuk membaca - sebanyak 3 :, read()
dan readAllBytes()
Kami readAllLines()
akan membahas yang terakhir secara rinci. Mengapa di atasnya? Karena memiliki tipe pengembalian yang sangat menarik - List<String>
! Artinya, ia mengembalikan kepada kita daftar baris dalam file. Tentu saja, hal ini membuat bekerja dengan konten menjadi sangat nyaman, karena seluruh file, baris demi baris, dapat, misalnya, dikeluarkan ke konsol dalam loop 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);
}
}
}
Keluaran konsol: Saya ingat momen indah: Anda muncul di hadapan saya, Seperti penglihatan sekilas, Seperti seorang jenius dengan kecantikan murni. Sangat nyaman! :) Fitur ini muncul di Java 7. Stream API muncul di Java 8 , yang menambahkan beberapa elemen pemrograman fungsional ke Java. Termasuk kemampuan yang lebih kaya untuk bekerja dengan file. Bayangkan kita mempunyai tugas: temukan semua baris dalam file yang dimulai dengan kata "Bagaimana", ubah menjadi UPPER CASE dan output ke konsol. Seperti apa solusi menggunakan kelas Files
di 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("How")) {
String upper = s.toUpperCase();
result.add(upper);
}
}
for (String s: result) {
System.out.println(s);
}
}
}
Keluaran konsol: SEPERTI VISI PUASA, SEPERTI SEORANG JENIUS KECANTIKAN MURNI. Sepertinya kita sudah melakukannya, tapi bukankah menurut Anda untuk tugas sederhana seperti itu, kode kita menjadi sedikit... bertele-tele? Menggunakan Java 8 Stream API, solusinya terlihat jauh 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("How"))
.map(String::toUpperCase)
.collect(Collectors.toList());
result.forEach(System.out::println);
}
}
Kami mencapai hasil yang sama, tetapi dengan kode yang jauh lebih sedikit! Selain itu, tidak dapat dikatakan bahwa kita kalah dalam “keterbacaan”. Saya pikir Anda dapat dengan mudah mengomentari apa yang dilakukan kode ini, bahkan jika Anda tidak terbiasa dengan Stream API. Namun singkatnya, Stream adalah rangkaian elemen di mana Anda dapat menjalankan berbagai fungsi. Kita mendapatkan objek Stream dari metode Files.lines()
dan kemudian menerapkan 3 fungsi ke dalamnya:
-
Dengan menggunakan metode ini,
filter()
kami hanya memilih baris-baris dari file yang dimulai dengan "Bagaimana". -
Kami menelusuri semua baris yang dipilih menggunakan metode ini
map()
dan mengurangi masing-masing baris menjadi HURUF BESAR. -
Kami menggabungkan semua garis yang dihasilkan menjadi
List
menggunakancollect()
.
Files.walkFileTree()
. Inilah yang perlu kita lakukan. Pertama, kita perlu FileVisitor
. FileVisitor
adalah antarmuka khusus yang menjelaskan semua metode untuk melintasi pohon file. Secara khusus, kami akan menempatkan logika di sana untuk membaca isi file dan memeriksa apakah berisi teks yang kami butuhkan. Seperti inilah tampilan kita nantinya 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("Required file found!");
System.out.println(file.toAbsolutePath());
break;
}
}
return FileVisitResult.CONTINUE;
}
}
Dalam hal ini, kelas kita mewarisi dari SimpleFileVisitor
. Ini adalah kelas yang mengimplementasikan FileVisitor
, di mana Anda hanya perlu mengganti satu metode: visitFile()
. Di sini kami menjelaskan apa yang perlu dilakukan dengan setiap file di setiap direktori. Jika Anda memerlukan logika traversal yang lebih kompleks, Anda harus menulis implementasi Anda sendiri FileVisitor
. Di sana Anda perlu menerapkan 3 metode lagi:
-
preVisitDirectory()
— logika yang harus dijalankan sebelum masuk ke folder; -
visitFileFailed()
— apa yang harus dilakukan jika memasukkan file tidak memungkinkan (tidak ada akses, atau alasan lain); -
postVisitDirectory()
— logika yang harus dijalankan setelah memasuki folder.
SimpleFileVisitor
. Logika di dalam metode ini visitFile()
cukup sederhana: baca semua baris dari file, periksa apakah berisi konten yang kita perlukan, dan jika ya, cetak jalur absolut ke konsol. Satu-satunya baris yang mungkin membuat Anda kesulitan adalah yang ini:
return FileVisitResult.CONTINUE;
Faktanya, semuanya sederhana. Di sini kami hanya menjelaskan apa yang harus dilakukan program setelah file dimasukkan dan semua operasi yang diperlukan telah diselesaikan. Dalam kasus kita, kita perlu terus melintasi pohon, jadi kita memilih opsi CONTINUE
. Tapi kita, misalnya, mungkin punya tugas lain: menemukan tidak semua file yang berisi "Ini adalah file yang kita perlukan", tetapi hanya satu file tersebut . Setelah itu, program harus dihentikan. Dalam hal ini, kode kita akan terlihat persis sama, tetapi bukannya break; akan:
return FileVisitResult.TERMINATE;
Baiklah, mari kita jalankan kode kita dan lihat apakah berhasil.
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: File yang diperlukan telah ditemukan! C:\Users\Username\Desktop\testFolder\FileWeNeed1.txt File yang diperlukan telah ditemukan! C:\Users\Username\Desktop\testFolder\level1-a\level2-aa\FileWeNeed2.txt File yang diperlukan telah ditemukan! C:\Users\Username\Desktop\testFolder\level1-b\level2-bb\FileWeNeed3.txt Hebat, kita berhasil! :) Jika Anda ingin tahu lebih banyak tentangnya walkFileTree()
, saya sarankan Anda artikel ini . Anda juga dapat menyelesaikan tugas kecil - menggantinya SimpleFileVisitor
dengan tugas biasa FileVisitor
, menerapkan keempat metode, dan menentukan tujuan program ini. Misalnya, Anda dapat menulis sebuah program yang akan mencatat semua tindakan Anda: menampilkan nama file atau folder di konsol sebelum/sesudah memasukkannya. Itu saja - sampai jumpa lagi! :)
GO TO FULL VERSION