JavaRush /Java Blog /Random-ID /File Java, Jalur

File Java, Jalur

Dipublikasikan di grup Random-ID
Halo! Hari ini kita akan berbicara tentang bekerja dengan file dan direktori. Anda sudah mengetahui cara mengelola konten file: kami memiliki banyak kelas yang dikhususkan untuk ini :) Saya rasa Anda dapat dengan mudah mengingat beberapa kelas yang diperlukan untuk tujuan ini. Dalam kuliah hari ini kita akan berbicara secara khusus tentang manajemen file - membuat, mengganti nama, dll. Sebelum Java 7, semua operasi tersebut dilakukan menggunakan 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 Filememiliki 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 Filememiliki cukup banyak metode yang mengembalikan booleannilai -. 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, Filemuncul sebanyak 3 kelas: Paths, Pathdan Files. Tepatnya, Pathini 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

Pathsadalah 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 Pathdan 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 , Pathnilai kembalian dari metode diurutkan. Di kelas, Filemetode 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, Pathmetode 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
    salah

    Perhatikan 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
    benar

    Anda 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 Pathsekelompok metode yang menyederhanakan pekerjaan dengan jalur absolut (penuh) dan relatif .

Mari kita lihat metode-metode ini:
  • 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

Daftar lengkap metodenya Pathcukup 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 Arraysor 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 Filesmengembalikan objekPath . Kebanyakan metode kelas Filesjuga 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 Filesmemungkinkan 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 Filesdi 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:
  1. Dengan menggunakan metode ini, filter()kami hanya memilih baris-baris dari file yang dimulai dengan "Bagaimana".

  2. Kami menelusuri semua baris yang dipilih menggunakan metode ini map()dan mengurangi masing-masing baris menjadi HURUF BESAR.

  3. Kami menggabungkan semua garis yang dihasilkan menjadi Listmenggunakan collect().

Pada akhirnya kita mendapatkan hasil yang sama: SEPERTI VISI PUASA, SEPERTI SEORANG JENIUS KECANTIKAN MURNI. Jika Anda tertarik untuk mempelajari lebih lanjut tentang kemampuan perpustakaan ini, kami sarankan membaca artikel ini . Kami akan kembali ke domba kami, yaitu file :) Kemungkinan terakhir yang akan kami pertimbangkan hari ini adalah menelusuri pohon file . Struktur file dalam sistem operasi modern paling sering berbentuk pohon: ia memiliki akar dan ada cabang yang dapat dipisahkan dari cabang lain, dll. Direktori memainkan peran root dan cabang. Misalnya, direktori “ C:// ” dapat bertindak sebagai root . Dua cabang bercabang darinya: “ C://Downloads ” dan “ C://Users ”. Dari masing-masing cabang tersebut terdapat 2 cabang lagi : “ C://Downloads/Pictures ”, “ C://Downloads/Video ”, “ C://Users/JohnSmith ”, “ C://Users/Pudge2005 ” . Cabang lain bercabang dari cabang ini, dan seterusnya. - beginilah hasil sebuah pohon. Di Linux tampilannya hampir sama, hanya saja di sana direktori tersebut bertindak sebagai root / File, Jalur - 2 Sekarang bayangkan kita memiliki tugas: mengetahui direktori root, kita harus menelusurinya, melihat ke dalam folder di semua tingkatan dan menemukan file di dalamnya dengan konten kita butuh. Kami akan mencari file yang berisi baris “Ini adalah file yang kami butuhkan!” Direktori root kami akan menjadi folder “testFolder”, yang terletak di desktop. Di dalamnya terdapat isi sebagai berikut: File, Jalur - 3Di dalam folder level1-a dan level1-b juga terdapat folder: File, Jalur - 4File, Jalur - 5Di dalam “folder tingkat kedua” ini tidak ada lagi folder, hanya file individual: File, Jalur - 6File, Jalur - 7Kami akan secara khusus menunjuk 3 file dengan konten yang kami perlu dengan nama yang jelas - FileWeNeed1.txt , FileWeNeed2.txt, FileWeNeed3.txt Inilah yang perlu kita temukan berdasarkan konten menggunakan Java. Bagaimana kita bisa melakukan ini? Metode yang sangat ampuh untuk melintasi pohon file datang untuk menyelamatkan - Files.walkFileTree(). Inilah yang perlu kita lakukan. Pertama, kita perlu FileVisitor. FileVisitoradalah 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.

Kami tidak punya logika seperti itu, jadi itu sudah cukup bagi kami 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 SimpleFileVisitordengan 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! :)
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION