API Jalur NIO2 Java

1. Ikhtisar

Pada artikel ini, kita akan mempelajari cara menggunakan Path API I / O (NIO2) baru di Java.

The Jalan API di NIO2 merupakan salah satu bidang fungsional utama baru yang dikirimkan dengan Java 7 dan secara khusus subset dari baru sistem file API bersama API File.

2. Penyiapan

Dukungan NIO2 dibundel dalam paket java.nio.file . Jadi menyiapkan proyek Anda untuk menggunakan Path API hanyalah masalah mengimpor semuanya dalam paket ini:

import java.nio.file.*;

Karena contoh kode dalam artikel ini mungkin akan berjalan di lingkungan yang berbeda, mari kita menangani direktori home pengguna:

private static String HOME = System.getProperty("user.home");

Variabel ini akan menunjuk ke lokasi yang valid di lingkungan mana pun.

Kelas Paths adalah titik masuk utama ke semua operasi yang melibatkan jalur sistem file. Ini memungkinkan kita untuk membuat dan memanipulasi jalur ke file dan direktori.

Patut dicatat adalah bahwa operasi jalur sebagian besar bersifat sintaksis; mereka tidak berpengaruh pada sistem file yang mendasarinya dan sistem file juga tidak berpengaruh pada apakah mereka berhasil atau gagal. Ini berarti bahwa meneruskan jalur yang tidak ada sebagai parameter operasi jalur tidak berpengaruh apakah berhasil atau gagal.

3. Operasi Jalur

Di bagian ini, kami akan memperkenalkan sintaks utama yang digunakan dalam operasi jalur. Sesuai dengan namanya, kelas Path adalah representasi programatik dari sebuah path dalam sistem file.

Sebuah Jalan objek berisi nama file dan direktori daftar digunakan untuk membangun jalan dan digunakan untuk memeriksa, mencari, dan memanipulasi file.

Kelas helper, java.nio.file.Paths (dalam bentuk jamak) adalah cara formal untuk membuat objek Path . Ini memiliki dua metode statis untuk membuat Path dari string jalur:

Path path = Paths.get("path string");

Apakah kita menggunakan maju atau mundur di jalur String, tidak masalah, API menyelesaikan parameter ini sesuai dengan persyaratan sistem file yang mendasarinya.

Dan dari objek java.net.URI :

Path path = Paths.get(URI object);

Sekarang kita dapat melanjutkan dan melihat ini beraksi.

4. Membuat Path

Untuk membuat objek Path dari string jalur:

@Test public void givenPathString_whenCreatesPathObject_thenCorrect() { Path p = Paths.get("/articles/baeldung"); assertEquals("\\articles\\baeldung", p.toString()); }

The get API dapat mengambil argumen parameter variabel bagian string path (dalam hal ini, artikel dan baeldung ) di samping bagian pertama (dalam hal ini, artikel ).

Jika kita menyediakan bagian-bagian ini alih-alih string jalur lengkap, mereka akan digunakan untuk membangun objek Path, kita tidak perlu menyertakan pemisah nama (garis miring) di bagian argumen variabel:

@Test public void givenPathParts_whenCreatesPathObject_thenCorrect() { Path p = Paths.get("/articles", "baeldung"); assertEquals("\\articles\\baeldung", p.toString()); }

5. Mengambil Informasi Jalur

Anda dapat menganggap objek Path sebagai elemen nama sebagai sebuah urutan. String path seperti E: \ baeldung \ articles \ java terdiri dari tiga elemen nama yaitu baeldung , artikel , dan java . Elemen tertinggi dalam struktur direktori akan ditempatkan pada indeks 0, dalam hal ini adalah baeldung .

Elemen terendah dalam struktur direktori akan ditempatkan di indeks [n-1] , di mana n adalah jumlah elemen nama di jalur. Elemen terendah ini disebut nama file terlepas dari apakah itu file yang sebenarnya atau bukan:

@Test public void givenPath_whenRetrievesFileName_thenCorrect() { Path p = Paths.get("/articles/baeldung/logs"); Path fileName = p.getFileName(); assertEquals("logs", fileName.toString()); }

Metode tersedia untuk mengambil elemen individu menurut indeks:

@Test public void givenPath_whenRetrievesNameByIndex_thenCorrect() { Path p = Paths.get("/articles/baeldung/logs"); Path name0 = getName(0); Path name1 = getName(1); Path name2 = getName(2); assertEquals("articles", name0.toString()); assertEquals("baeldung", name1.toString()); assertEquals("logs", name2.toString()); }

atau sub-urutan jalur menggunakan rentang indeks ini:

@Test public void givenPath_whenCanRetrieveSubsequenceByIndex_thenCorrect() { Path p = Paths.get("/articles/baeldung/logs"); Path subPath1 = p.subpath(0,1); Path subPath2 = p.subpath(0,2); assertEquals("articles", subPath1.toString()); assertEquals("articles\\baeldung", subPath2.toString()); assertEquals("articles\\baeldung\\logs", p.subpath(0, 3).toString()); assertEquals("baeldung", p.subpath(1, 2).toString()); assertEquals("baeldung\\logs", p.subpath(1, 3).toString()); assertEquals("logs", p.subpath(2, 3).toString()); }

Setiap jalur dikaitkan dengan jalur induk atau null jika jalur tersebut tidak memiliki induk. Induk objek jalur terdiri dari komponen akar jalur, jika ada, dan setiap elemen di jalur tersebut kecuali untuk nama file. Sebagai contoh, path induk dari / a / b / c adalah / a / b dan dari / a adalah null:

@Test public void givenPath_whenRetrievesParent_thenCorrect() { Path p1 = Paths.get("/articles/baeldung/logs"); Path p2 = Paths.get("/articles/baeldung"); Path p3 = Paths.get("/articles"); Path p4 = Paths.get("/"); Path parent1 = p1.getParent(); Path parent2 = p2.getParent(); Path parent3 = p3.getParent(); Path parent4 = p4.getParenth(); assertEquals("\\articles\\baeldung", parent1.toString()); assertEquals("\\articles", parent2.toString()); assertEquals("\\", parent3.toString()); assertEquals(null, parent4); }

Kita juga bisa mendapatkan elemen root dari sebuah jalur:

@Test public void givenPath_whenRetrievesRoot_thenCorrect() { Path p1 = Paths.get("/articles/baeldung/logs"); Path p2 = Paths.get("c:/articles/baeldung/logs"); Path root1 = p1.getRoot(); Path root2 = p2.getRoot(); assertEquals("\\", root1.toString()); assertEquals("c:\\", root2.toString()); }

6. Normalisasi Path

Banyak sistem file menggunakan "." notasi untuk menunjukkan direktori saat ini dan ".." untuk menunjukkan direktori induk. Anda mungkin mengalami situasi di mana jalur berisi informasi direktori yang berlebihan.

Misalnya, pertimbangkan string jalur berikut:

/baeldung/./articles /baeldung/authors/../articles /baeldung/articles

They all resolve to the same location /baeldung/articles. The first two have redundancies while the last one does not.

Normalizing a path involves removing redundancies in it. The Path.normalize() operation is provided for this purpose.

This example should now be self-explanatory:

@Test public void givenPath_whenRemovesRedundancies_thenCorrect1() { Path p = Paths.get("/home/./baeldung/articles"); Path cleanPath = p.normalize(); assertEquals("\\home\\baeldung\\articles", cleanPath.toString()); }

This one too:

@Test public void givenPath_whenRemovesRedundancies_thenCorrect2() { Path p = Paths.get("/home/baeldung/../articles"); Path cleanPath = p.normalize(); assertEquals("\\home\\articles", cleanPath.toString()); }

7. Path Conversion

There are operations to convert a path to a chosen presentation format. To convert any path into a string that can be opened from the browser, we use the toUri method:

@Test public void givenPath_whenConvertsToBrowseablePath_thenCorrect() { Path p = Paths.get("/home/baeldung/articles.html"); URI uri = p.toUri(); assertEquals( "file:///E:/home/baeldung/articles.html", uri.toString()); }

We can also convert a path to its absolute representation. The toAbsolutePath method resolves a path against a file system default directory:

@Test public void givenPath_whenConvertsToAbsolutePath_thenCorrect() { Path p = Paths.get("/home/baeldung/articles.html"); Path absPath = p.toAbsolutePath(); assertEquals( "E:\\home\\baeldung\\articles.html", absPath.toString()); }

However, when the path to be resolved is detected to be already absolute, the method returns it as is:

@Test public void givenAbsolutePath_whenRetainsAsAbsolute_thenCorrect() { Path p = Paths.get("E:\\home\\baeldung\\articles.html"); Path absPath = p.toAbsolutePath(); assertEquals( "E:\\home\\baeldung\\articles.html", absPath.toString()); }

We can also convert any path to its real equivalent by calling the toRealPath method. This method tries to resolve the path by mapping it's elements to actual directories and files in the file system.

Time to use the variable we created in the Setup section which points to logged-in user's home location in the file system:

@Test public void givenExistingPath_whenGetsRealPathToFile_thenCorrect() { Path p = Paths.get(HOME); Path realPath = p.toRealPath(); assertEquals(HOME, realPath.toString()); }

The above test does not really tell us much about the behavior of this operation. The most obvious result is that if the path does not exist in the file system, then the operation will throw an IOException, read on.

For the lack of a better way to drive this point home, just take a look at the next test, which attempts to convert an inexistent path to a real path:

@Test(expected = NoSuchFileException.class) public void givenInExistentPath_whenFailsToConvert_thenCorrect() { Path p = Paths.get("E:\\home\\baeldung\\articles.html"); p.toRealPath(); }

The test succeeds when we catch an IOException. The actual subclass of IOException that this operation throws is NoSuchFileException.

8. Joining Paths

Joining any two paths can be achieved using the resolve method.

Simply put, we can call the resolve method on any Path and pass in a partial path as the argument. That partial path is appended to the original path:

@Test public void givenTwoPaths_whenJoinsAndResolves_thenCorrect() { Path p = Paths.get("/baeldung/articles"); Path p2 = p.resolve("java"); assertEquals("\\baeldung\\articles\\java", p2.toString()); }

However, when the path string passed to the resolve method is not a partial path; most notably an absolute path, then the passed-in path is returned:

@Test public void givenAbsolutePath_whenResolutionRetainsIt_thenCorrect() { Path p = Paths.get("/baeldung/articles"); Path p2 = p.resolve("C:\\baeldung\\articles\java"); assertEquals("C:\\baeldung\\articles\\java", p2.toString()); }

The same thing happens with any path that has a root element. The path string “java” has no root element while the path string “/java” has a root element. Therefore, when you pass in a path with a root element, it is returned as is:

@Test public void givenPathWithRoot_whenResolutionRetainsIt_thenCorrect2() { Path p = Paths.get("/baeldung/articles"); Path p2 = p.resolve("/java"); assertEquals("\\java", p2.toString()); }

9. Relativizing Paths

The term relativizing simply means creating a direct path between two known paths. For instance, if we have a directory /baeldung and inside it, we have two other directories such that /baeldung/authors and /baeldung/articles are valid paths.

The path to articles relative to authors would be described as “move one level up in the directory hierarchy then into articles directory” or ..\articles:

@Test public void givenSiblingPaths_whenCreatesPathToOther_thenCorrect() { Path p1 = Paths.get("articles"); Path p2 = Paths.get("authors"); Path p1_rel_p2 = p1.relativize(p2); Path p2_rel_p1 = p2.relativize(p1); assertEquals("..\\authors", p1_rel_p2.toString()); assertEquals("..\\articles", p2_rel_p1.toString()); }

Assuming we move the articles directory to authors folder such that they are no longer siblings. The following relativizing operations involve creating a path between baeldung and articles and vice versa:

@Test public void givenNonSiblingPaths_whenCreatesPathToOther_thenCorrect() { Path p1 = Paths.get("/baeldung"); Path p2 = Paths.get("/baeldung/authors/articles"); Path p1_rel_p2 = p1.relativize(p2); Path p2_rel_p1 = p2.relativize(p1); assertEquals("authors\\articles", p1_rel_p2.toString()); assertEquals("..\\..", p2_rel_p1.toString()); }

10. Comparing Paths

The Path class has an intuitive implementation of the equals method which enables us to compare two paths for equality:

@Test public void givenTwoPaths_whenTestsEquality_thenCorrect() { Path p1 = Paths.get("/baeldung/articles"); Path p2 = Paths.get("/baeldung/articles"); Path p3 = Paths.get("/baeldung/authors"); assertTrue(p1.equals(p2)); assertFalse(p1.equals(p3)); }

You can also check if a path begins with a given string:

@Test public void givenPath_whenInspectsStart_thenCorrect() { Path p1 = Paths.get("/baeldung/articles"); assertTrue(p1.startsWith("/baeldung")); }

Or ends with some other string:

@Test public void givenPath_whenInspectsEnd_thenCorrect() { Path p1 = Paths.get("/baeldung/articles"); assertTrue(p1.endsWith("articles")); }

11. Conclusion

Di artikel ini, kami menunjukkan operasi Path di API sistem file baru (NIO2) yang dikirimkan sebagai bagian dari Java 7 dan melihat sebagian besar dari mereka beraksi.

Contoh kode yang digunakan dalam artikel ini dapat ditemukan di proyek Github artikel.