File
. Maaari mong basahin ang tungkol sa kanyang trabaho dito . Ngunit sa Java 7, nagpasya ang mga tagalikha ng wika na baguhin kung paano sila gumagana sa mga file at direktoryo. Ito ay dahil sa ang katunayan na ang klase File
ay may ilang mga disadvantages. Halimbawa, wala itong paraan copy()
na magbibigay-daan sa iyong kopyahin ang isang file mula sa isang lokasyon patungo sa isa pa (isang tila malinaw na kinakailangang tampok). Bilang karagdagan, ang klase File
ay may napakaraming pamamaraan na nagbalik boolean
ng -values. Kung may naganap na error, ang ganitong paraan ay nagbabalik ng false sa halip na maghagis ng exception, na nagpapahirap sa pag-diagnose ng mga error at pagtukoy sa mga sanhi ng mga ito. Sa halip na isang klase, File
kasing dami ng 3 klase ang lumitaw: Paths
, Path
at Files
. Well, upang maging tumpak, Path
ito ay isang interface, hindi isang klase. Alamin natin kung paano sila naiiba sa isa't isa at kung bakit kailangan ang bawat isa sa kanila. Magsimula tayo sa pinakamadaling bagay - Paths
.
Mga landas
Paths
ay isang napakasimpleng klase na may isang solong static na pamamaraan get()
. Ito ay nilikha lamang upang makakuha ng isang bagay na may uri mula sa naipasa na string o URI Path
. Wala itong ibang pag-andar. Narito ang isang halimbawa ng kanyang trabaho:
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");
}
}
Hindi ang pinakamahirap na klase, tama ba? :) Well, dahil nakakuha kami ng isang object ng uri Path
, alamin natin kung ano ito Path
at kung bakit ito kinakailangan :)
Daan
Path
, sa pangkalahatan, ay isang muling idinisenyong analogue ng File
. Ito ay mas madaling magtrabaho kasama kaysa sa File
. Una , maraming mga utility (static) na pamamaraan ang inalis dito at inilipat sa class Files
. Pangalawa , Path
ang mga halaga ng pagbabalik ng mga pamamaraan ay iniutos. Sa klase, File
ibinalik ng mga pamamaraan ito String
, iyon boolean
, iyon File
- hindi madaling malaman. Halimbawa, mayroong isang paraan getParent()
na nagbalik sa parent path para sa kasalukuyang file bilang isang string. Ngunit sa parehong oras mayroong isang paraan getParentFile()
na nagbalik ng parehong bagay, ngunit sa anyo ng isang bagay File
! Ito ay malinaw na kalabisan. Samakatuwid, sa interface, Path
ang pamamaraan getParent()
at iba pang mga pamamaraan para sa pagtatrabaho sa mga file ay nagbabalik lamang ng isang bagay Path
. Walang tambak ng mga pagpipilian - lahat ay madali at simple. Anong mga kapaki-pakinabang na pamamaraan mayroon ito Path
? Narito ang ilan sa kanila at mga halimbawa ng kanilang trabaho:
-
getFileName()
— ibinabalik ang pangalan ng file mula sa landas; -
getParent()
— ibinabalik ang direktoryo ng "magulang" na may kaugnayan sa kasalukuyang landas (iyon ay, ang direktoryo na mas mataas sa puno ng direktoryo); -
getRoot()
— ibinabalik ang "root" na direktoryo; iyon ay, ang isa na nasa tuktok ng puno ng direktoryo; -
startsWith()
,endsWith()
— suriin kung ang landas ay nagsisimula/nagtatapos sa naipasa na landas: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 ng console:
testFile.txt
C:\Users\Username\Desktop
C:\
true
falseBigyang-pansin kung paano gumagana ang pamamaraan
endsWith()
. Sinusuri nito kung ang kasalukuyang landas ay nagtatapos sa naipasa na landas . Ito ay nasa landas , at hindi sa hanay ng mga karakter .Ihambing ang mga resulta ng dalawang tawag na ito:
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 ng console:
mali
totooKailangan mong ipasa ang buong landas sa pamamaraan
endsWith()
, at hindi lamang isang hanay ng mga character: kung hindi, ang resulta ay palaging mali , kahit na ang kasalukuyang landas ay aktwal na nagtatapos sa gayong pagkakasunud-sunod ng mga character (tulad ng sa kaso ng "estFile.txt ” sa halimbawa sa itaas).Bilang karagdagan, mayroong
Path
isang pangkat ng mga pamamaraan na pinapasimple ang pagtatrabaho sa ganap (buo) at kamag-anak na mga landas .
-
boolean isAbsolute()
— nagbabalik ng true kung ang kasalukuyang landas ay ganap: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 ng console:
totoo
-
Path normalize()
— "pinag-normalize" ang kasalukuyang landas, inaalis ang mga hindi kinakailangang elemento mula dito. Maaaring alam mo na ang mga sikat na operating system ay kadalasang gumagamit ng mga "." character kapag nagsasaad ng mga landas. (“kasalukuyang direktoryo”) at “..” (direktoryo ng magulang). Halimbawa: " ./Pictures/dog.jpg " ay nangangahulugan na sa direktoryo na kinaroroonan natin ngayon, mayroong folder ng Pictures, at doon ay may file na "dog.jpg"Kaya eto na. Kung ang iyong programa ay may landas na gumagamit ng "."
normalize()
o "..", aalisin sila ng pamamaraan at makakakuha ng landas na hindi naglalaman ng mga ito: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 ng console:
C:\Users\Java\examps
C:\Users\examps -
Path relativize()
— kinakalkula ang kamag-anak na landas sa pagitan ng kasalukuyang at dumaan na landas.Halimbawa:
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 ng console:
Username\Desktop\testFile.txt
Path
ay medyo malaki. Mahahanap mo silang lahat sa dokumentasyon ng Oracle . Magpapatuloy tayo sa pagsusuri Files
.
Mga file
Files
- ito ay isang utility class kung saan ang mga static na pamamaraan mula sa klase ay inilipat File
. Files
- ito ay humigit-kumulang kapareho ng Arrays
o Collections
, gumagana lamang ito sa mga file, at hindi sa mga array at koleksyon :) Nakatuon ito sa pamamahala ng mga file at direktoryo. Gamit ang mga static na pamamaraan Files
, maaari tayong lumikha, magtanggal at maglipat ng mga file at direktoryo. Para sa mga operasyong ito ang mga pamamaraan ay ginagamit createFile()
(para sa mga direktoryo - createDirectory()
), move()
at delete()
. Narito kung paano gamitin ang mga ito:
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")));
}
}
Dito muna tayo lumikha ng isang file (pamamaraan Files.createFile()
) sa desktop, pagkatapos ay lumikha ng isang folder doon (pamamaraan Files.createDirectory()
). Pagkatapos nito, inililipat namin ang file (paraan Files.move()
) mula sa desktop patungo sa bagong folder na ito, at sa dulo ay tinatanggal namin ang file (paraan Files.delete()
). Output ng console: Matagumpay bang nalikha ang file? true Matagumpay bang nalikha ang direktoryo? true Nasa desktop pa ba ang file natin? false Nailipat ba ang aming file sa testDirectory? totoo Umiiral pa ba ang file? mali Bigyang-pansin:Tulad ng mga pamamaraan ng interface Path
, maraming mga pamamaraan Files
ang nagbabalik ng isang bagayPath
. Karamihan sa mga pamamaraan ng klase Files
ay tinatanggap din Path
. Narito ang isang paraan ay magiging iyong tapat na katulong Paths.get()
- gamitin ito nang aktibo. Ano pa ang kawili-wili sa Files
? Ang talagang kulang sa lumang klase ay ang pamamaraang ! File
. copy()
Napag-usapan namin siya sa simula ng lecture, ngayon na ang oras upang makilala siya!
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 ng console: Matagumpay bang nalikha ang file? true Matagumpay bang nalikha ang direktoryo? true Nasa desktop pa rin ba ang file natin? true Nakopya ba ang aming file sa testDirectory? true Ngayon ay maaari mong kopyahin ang mga file sa programmatically! :) Ngunit pinapayagan ka ng klase Files
hindi lamang na pamahalaan ang mga file sa kanilang sarili, kundi pati na rin upang gumana sa mga nilalaman nito. Upang magsulat ng data sa isang file, mayroon itong paraan write()
, at para sa pagbabasa - kasing dami ng 3:, read()
at Tatalakayin readAllBytes()
namin ang huli nang detalyado. readAllLines()
Bakit sa ito? Dahil mayroon itong isang napaka-interesante na uri ng pagbabalik - List<String>
! Ibig sabihin, ibinabalik nito sa amin ang isang listahan ng mga linya sa file. Siyempre, ginagawa nitong maginhawa ang pagtatrabaho sa nilalaman, dahil ang buong file, linya sa linya, ay maaaring, halimbawa, maging output sa console sa isang regular na loop 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 ng console: Naaalala ko ang isang napakagandang sandali: Nagpakita ka sa harap ko, Tulad ng panandaliang pangitain, Tulad ng isang henyo ng dalisay na kagandahan. Napakakomportable! :) Lumitaw ang feature na ito sa Java 7. Sa Java 8, lumitaw ang Stream API , na nagdagdag ng ilang elemento ng functional programming sa Java. Kabilang ang mas mahusay na mga kakayahan sa pamamahala ng file. Isipin na mayroon kaming isang gawain: hanapin ang lahat ng mga linya sa isang file na nagsisimula sa salitang "Paano", i-convert ang mga ito sa UPPER CASE at i-output ang mga ito sa console. Files
Ano ang magiging hitsura ng isang solusyon gamit ang isang klase sa Java 7? Isang bagay na tulad nito:
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);
}
}
}
Output ng console: TULAD NG ISANG FASTING VISION, PARANG HENIUS OF PURE BEAUTY. Mukhang nagawa na namin ito, ngunit hindi mo ba naisip na para sa isang simpleng gawain ang aming code ay naging isang maliit na ... verbose? Gamit ang Java 8 Stream API ang solusyon ay mukhang mas eleganteng:
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);
}
}
Nakamit namin ang parehong resulta, ngunit may mas kaunting code! Bukod dito, hindi masasabing natalo tayo sa “readability”. Sa tingin ko madali kang makakapagkomento sa kung ano ang ginagawa ng code na ito, kahit na hindi ka pamilyar sa Stream API. Ngunit sa madaling salita, ang Stream ay isang pagkakasunud-sunod ng mga elemento kung saan maaari kang magsagawa ng iba't ibang mga function. Nakukuha namin ang Stream object mula sa pamamaraan Files.lines()
at pagkatapos ay ilapat ang 3 function dito:
-
Gamit ang pamamaraan,
filter()
pipiliin lamang namin ang mga linyang iyon mula sa file na nagsisimula sa "Paano". -
Dinadaanan namin ang lahat ng napiling row gamit ang pamamaraan
map()
at binabawasan ang bawat isa sa kanila sa UPPER CASE. -
Pinagsasama namin ang lahat ng nagresultang linya sa
List
paggamit ngcollect()
.
Files.walkFileTree()
. Narito ang kailangan nating gawin. Una, kailangan natin FileVisitor
. FileVisitor
ay isang espesyal na interface na naglalarawan sa lahat ng mga pamamaraan para sa pagtawid sa file tree. Sa partikular, maglalagay kami ng lohika doon upang basahin ang mga nilalaman ng file at suriin kung naglalaman ito ng teksto na kailangan namin. Ito ang magiging hitsura natin 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;
}
}
Sa kasong ito, nagmamana ang aming klase mula sa SimpleFileVisitor
. Ito ay isang klase na nagpapatupad ng FileVisitor
, kung saan kailangan mong i-override ang isang paraan lamang: visitFile()
. Dito inilalarawan namin kung ano ang kailangang gawin sa bawat file sa bawat direktoryo. Kung kailangan mo ng mas kumplikadong traversal logic, dapat mong isulat ang iyong sariling pagpapatupad FileVisitor
. Doon ay kakailanganin mong ipatupad ang 3 higit pang mga pamamaraan:
-
preVisitDirectory()
— lohika na dapat isagawa bago ipasok ang folder; -
visitFileFailed()
— ano ang gagawin kung imposible ang pagpasok ng file (walang access, o iba pang dahilan); -
postVisitDirectory()
— ang lohika na dapat isagawa pagkatapos ipasok ang folder.
SimpleFileVisitor
. Ang lohika sa loob ng pamamaraan visitFile()
ay medyo simple: basahin ang lahat ng mga linya mula sa file, suriin kung naglalaman ang mga ito ng nilalaman na kailangan namin, at kung gayon, i-print ang ganap na landas sa console. Ang tanging linya na maaaring magbigay sa iyo ng problema ay ang isang ito:
return FileVisitResult.CONTINUE;
Sa katunayan, ang lahat ay simple. Dito ay inilalarawan lamang namin kung ano ang dapat gawin ng programa pagkatapos maipasok ang file at makumpleto ang lahat ng kinakailangang operasyon. Sa aming kaso, kailangan naming ipagpatuloy ang pagtawid sa puno, kaya pipiliin namin ang opsyon CONTINUE
. Ngunit kami, halimbawa, ay maaaring magkaroon ng isa pang gawain: upang mahanap hindi lahat ng mga file na naglalaman ng "Ito ang file na kailangan namin", ngunit isa lamang ang ganoong file . Pagkatapos nito, dapat na wakasan ang programa. Sa kasong ito, ang aming code ay magiging eksaktong pareho, ngunit sa halip na break; ay:
return FileVisitResult.TERMINATE;
Well, patakbuhin natin ang ating code at tingnan kung gumagana ito.
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 ng console: Nahanap na ang kinakailangang file! C:\Users\Username\Desktop\testFolder\FileWeNeed1.txt Nahanap ang kinakailangang file! C:\Users\Username\Desktop\testFolder\level1-a\level2-aa\FileWeNeed2.txt Nahanap ang kinakailangang file! C:\Users\Username\Desktop\testFolder\level1-b\level2-bb\FileWeNeed3.txt Mahusay, nagawa namin ito! :) Kung gusto mong malaman ang higit pa tungkol sa walkFileTree()
, inirerekomenda ko sa iyo ang artikulong ito . Maaari mo ring kumpletuhin ang isang maliit na gawain - palitan ito SimpleFileVisitor
ng regular FileVisitor
, ipatupad ang lahat ng 4 na pamamaraan at magkaroon ng layunin para sa program na ito. Halimbawa, maaari kang magsulat ng isang programa na magla-log sa lahat ng iyong mga aksyon: ipakita ang pangalan ng isang file o folder sa console bago/pagkatapos ipasok ang mga ito. Iyon lang - see you later! :)
GO TO FULL VERSION