php的網(wǎng)站/新聞?lì)^條新聞
一、全文概覽
在學(xué)習(xí)文件系統(tǒng)之前,需要了解下Java在I/O上的發(fā)展史:在Java7之前,打開和讀取文件需要編寫特別笨拙的代碼,涉及到很多的InputStream、OutputStream等組合起來(lái)使用,每次在使用時(shí)或許都需要查一下文檔才能記得如何打開一個(gè)文件;而在Java 7面世后,這些被人詬病的設(shè)計(jì)得到了巨大的改進(jìn),這些新元素被打包放在了java.nio.file之下。這個(gè)包對(duì)Java對(duì)文件的操作提升到了可以與其他編程語(yǔ)言媲美的程度。
本篇文章就主要學(xué)習(xí)記錄下操作文件的兩個(gè)基本組件:
- 文件或目錄的路徑-Path
- 文件本身-File
二、組件一:Path(路徑)
1、Path簡(jiǎn)介
Path對(duì)象代表的是一個(gè)文件或目錄的路徑,它是在不同的操作系統(tǒng)和文件系統(tǒng)之上的抽象。它的目的是,我們不必要注意底層的操作系統(tǒng),我們的代碼不需要重寫就能在不同的操作系統(tǒng)上工作 —來(lái)自:《OnJava-基礎(chǔ)篇》
2、Path創(chuàng)建
介紹完P(guān)ath出現(xiàn)的目的后,我們?cè)賮?lái)看下如果獲取Path。正是java.nio.file.Paths類下重載的static get方法,這個(gè)方法的參數(shù)可以是接受一個(gè)String序列(也就是全路徑,系統(tǒng)能夠找到的);也可以是一個(gè)統(tǒng)一的資源標(biāo)識(shí)符(URI),然后將其轉(zhuǎn)換為Path
下面是對(duì)Path以及Files工具類的使用示例
package com.markus.java.file;import com.markus.java.file.constant.FileConstant;import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;/*** @Author: zhangchenglong06* @Date: 2023/2/7* @Description:*/
public class PathInfo {static void show(String id, Object p) {System.out.println(id + p);}static void info(Path path) {show("toString: \n", path);// 路徑是否存在show("Exists: ", Files.exists(path));// 是否是常規(guī)文件,也就是我們常規(guī)意義上的文件,例如.txt .png等,而非目錄show("RegularFile: ", Files.isRegularFile(path));// 是否是目錄show("Directory: ", Files.isDirectory(path));// 展示絕對(duì)路徑show("Absolute: ", path.toAbsolutePath());// 展示文件名(最后一級(jí))show("FileName: ", path.getFileName());// 展示父路徑show("Parent: ", path.getParent());// 展示根路徑show("Root: ", path.getRoot());System.out.println("****************************************************************************************");}public static void main(String[] args) {System.out.println(System.getProperty("os.name"));info(FileSystems.getDefault().getPath(""));info(Paths.get("io/src/main/resources", "file", "file.txt"));Path path = Paths.get(FileConstant.CURRENT_BASE_PATH, "/PathInfo.java");info(path);Path ap = path.toAbsolutePath();info(ap);info(ap.getParent());try {info(ap.toRealPath());} catch (IOException e) {System.out.println(e);}URI uri = path.toUri();System.out.println("URI:\n" + uri);Path pathUri = Paths.get(uri);System.out.println(Files.exists(pathUri));// 不要被騙了File f = ap.toFile();}
}
/** 輸出* Mac OS X* toString:** Exists: true* RegularFile: false* Directory: true* Absolute: /Users/zhangchenglong/IdeaProjects/OnJava8-Examples* FileName:* Parent: null* Root: null* ***************************************************************************************** toString:* io/src/main/resources/file/file.txt* Exists: false* RegularFile: false* Directory: false* Absolute: /Users/zhangchenglong/IdeaProjects/OnJava8-Examples/io/src/main/resources/file/file.txt* FileName: file.txt* Parent: io/src/main/resources/file* Root: null* ***************************************************************************************** toString:* io/src/main/java/com/markus/java/file/PathInfo.java* Exists: true* RegularFile: true* Directory: false* Absolute: /Users/zhangchenglong/IdeaProjects/OnJava8-Examples/io/src/main/java/com/markus/java/file/PathInfo.java* FileName: PathInfo.java* Parent: io/src/main/java/com/markus/java/file* Root: null* ***************************************************************************************** toString:* /Users/zhangchenglong/IdeaProjects/OnJava8-Examples/io/src/main/java/com/markus/java/file/PathInfo.java* Exists: true* RegularFile: true* Directory: false* Absolute: /Users/zhangchenglong/IdeaProjects/OnJava8-Examples/io/src/main/java/com/markus/java/file/PathInfo.java* FileName: PathInfo.java* Parent: /Users/zhangchenglong/IdeaProjects/OnJava8-Examples/io/src/main/java/com/markus/java/file* Root: /* ***************************************************************************************** toString:* /Users/zhangchenglong/IdeaProjects/OnJava8-Examples/io/src/main/java/com/markus/java/file* Exists: true* RegularFile: false* Directory: true* Absolute: /Users/zhangchenglong/IdeaProjects/OnJava8-Examples/io/src/main/java/com/markus/java/file* FileName: file* Parent: /Users/zhangchenglong/IdeaProjects/OnJava8-Examples/io/src/main/java/com/markus/java* Root: /* ***************************************************************************************** toString:* /Users/zhangchenglong/IdeaProjects/OnJava8-Examples/io/src/main/java/com/markus/java/file/PathInfo.java* Exists: true* RegularFile: true* Directory: false* Absolute: /Users/zhangchenglong/IdeaProjects/OnJava8-Examples/io/src/main/java/com/markus/java/file/PathInfo.java* FileName: PathInfo.java* Parent: /Users/zhangchenglong/IdeaProjects/OnJava8-Examples/io/src/main/java/com/markus/java/file* Root: /* ***************************************************************************************** URI:* file:///Users/zhangchenglong/IdeaProjects/OnJava8-Examples/io/src/main/java/com/markus/java/file/PathInfo.java* true** Process finished with exit code 0*/
3、Path片段
所謂Path片段即是Path對(duì)象路徑的各個(gè)部分,例如/Users/zhangchenglong/IdeaProjects/OnJava8-Examples/io/src/main/java/com/markus/java中每個(gè)//之間的內(nèi)容都是一個(gè)片段
package com.markus.java.file;import com.markus.java.file.constant.FileConstant;import java.nio.file.Path;
import java.nio.file.Paths;/*** @Author: zhangchenglong06* @Date: 2023/2/7* @Description:*/
public class PartsOfPaths {public static void main(String[] args) {System.out.println(System.getProperty("os.name"));Path p = Paths.get(FileConstant.CURRENT_BASE_PATH, "/PartsOfPaths.java");for (int i = 0; i < p.getNameCount(); i++) {System.out.println(p.getName(i));}System.out.println("ends with '.java': " + p.endsWith(".java"));for (Path path : p) {System.out.print(path + ": ");System.out.print(p.startsWith(path) + " : ");System.out.println(p.endsWith(path));}System.out.println("Starts with " + p.toAbsolutePath().getRoot() + " " + p.toAbsolutePath().startsWith(p.toAbsolutePath().getRoot()));}
}
/** 輸出* Mac OS X* io* src* main* java* com* markus* java* file* PartsOfPaths.java* ends with '.java': false* io: true : false* src: false : false* main: false : false* java: false : false* com: false : false* markus: false : false* java: false : false* file: false : false* PartsOfPaths.java: false : true* Starts with / true*/
我們還可以對(duì)片段進(jìn)行添加和刪除,需要學(xué)習(xí)api如下:
- Path#relativize : 在路徑首部刪除基準(zhǔn)路徑形成新的路徑
- Path#normalize : 刪除冗余名稱元素的路徑
- Path#resolve : 在Path對(duì)象后面增加路徑片段
package com.markus.java.file;import com.markus.java.file.constant.FileConstant;import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;/*** @Author: zhangchenglong06* @Date: 2023/2/8* @Description: 添加或刪除路徑片段* relativize 刪除基準(zhǔn)路徑* resolve 增加路徑*/
public class AddAndSubtractPaths {static Path base = Paths.get("..", "..", "..").toAbsolutePath().normalize();static void show(int id, Path result) {if (result.isAbsolute()) {// result 在 路徑首部刪除base基準(zhǔn)路徑形成新的路徑System.out.println("(" + id + ")r" + base.relativize(result));} else {System.out.println("(" + id + ")" + result);}try {System.out.println("RealPath: " + result.toRealPath());} catch (IOException e) {System.out.println(e);}}public static void main(String[] args) {System.out.println(System.getProperty("os.name"));System.out.println(base);Path p = Paths.get(FileConstant.CURRENT_BASE_PATH, "/AddAndSubtractPaths.java").toAbsolutePath();show(1, p);Path convoluted = p.getParent().getParent().resolve("strings").resolve("..").resolve(p.getParent().getFileName());show(2, convoluted);show(3, convoluted.normalize());Path p2 = Paths.get("..", "..");show(4, p2);// normalize 意為刪除了冗余名稱元素的路徑// 例如 ./ 直接刪除即可// 例如 strings/../ 直接刪除兩個(gè)元素即可show(5, p2.normalize());show(6, p2.toAbsolutePath());Path p3 = Paths.get(".").toAbsolutePath();// p3在自身路徑后面追加p2組成新的路徑Path p4 = p3.resolve(p2);show(7, p4);show(8, p4.normalize());Path p5 = Paths.get("").toAbsolutePath();show(9, p5);show(10, p5.resolveSibling("strings"));show(11, Paths.get("nonexistent"));}
}
/** 輸出* Mac OS X* /Users* (1)rzhangchenglong/IdeaProjects/OnJava8-Examples/io/src/main/java/com/markus/java/file/AddAndSubtractPaths.java* RealPath: /Users/zhangchenglong/IdeaProjects/OnJava8-Examples/io/src/main/java/com/markus/java/file/AddAndSubtractPaths.java* (2)rzhangchenglong/IdeaProjects/OnJava8-Examples/io/src/main/java/com/markus/java/strings/../file* java.nio.file.NoSuchFileException: /Users/zhangchenglong/IdeaProjects/OnJava8-Examples/io/src/main/java/com/markus/java/strings/../file* (3)rzhangchenglong/IdeaProjects/OnJava8-Examples/io/src/main/java/com/markus/java/file* RealPath: /Users/zhangchenglong/IdeaProjects/OnJava8-Examples/io/src/main/java/com/markus/java/file* (4)../..* RealPath: /Users/zhangchenglong* (5)../..* RealPath: /Users/zhangchenglong* (6)rzhangchenglong/IdeaProjects/OnJava8-Examples/../..* RealPath: /Users/zhangchenglong* (7)rzhangchenglong/IdeaProjects/OnJava8-Examples/./../..* RealPath: /Users/zhangchenglong* (8)rzhangchenglong* RealPath: /Users/zhangchenglong* (9)rzhangchenglong/IdeaProjects/OnJava8-Examples* RealPath: /Users/zhangchenglong/IdeaProjects/OnJava8-Examples* (10)rzhangchenglong/IdeaProjects/strings* java.nio.file.NoSuchFileException: /Users/zhangchenglong/IdeaProjects/strings* (11)nonexistent* java.nio.file.NoSuchFileException: nonexistent*/
4、刪除目錄
Files工具類包含了操作目錄和文件所需要的大部分操作,但其中缺乏刪除目錄樹的工具方法,這里我們做個(gè)刪除目錄樹工具的練習(xí)
package com.markus.java.file;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;/*** @Author: zhangchenglong06* @Date: 2023/2/9* @Description:*/
public class RmDir {public static void rmdir(Path dir) throws IOException {Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {/*** 在這個(gè)目錄下的每個(gè)文件上運(yùn)行* @param file* @param attrs* @return* @throws IOException*/@Overridepublic FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {Files.delete(file);return FileVisitResult.CONTINUE;}/*** 先進(jìn)入當(dāng)前目錄下的文件和目錄(包括所有的子目錄),最后在當(dāng)前目錄上運(yùn)行* @param dir* @param exc* @return* @throws IOException*/@Overridepublic FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {Files.delete(dir);return FileVisitResult.CONTINUE;}/*** 先在當(dāng)前目錄上運(yùn)行,然后進(jìn)入這個(gè)目錄下的文件和目錄* @param dir* @param attrs* @return* @throws IOException*/@Overridepublic FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {return super.preVisitDirectory(dir, attrs);}/*** 當(dāng)文件無(wú)法訪問(wèn)時(shí)調(diào)用* @param file* @param exc* @return* @throws IOException*/@Overridepublic FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {return super.visitFileFailed(file, exc);}});}
}
下面來(lái)檢驗(yàn)下刪除工具的有效性
package com.markus.java.file;import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;import static com.markus.java.file.constant.FileConstant.CURRENT_BASE_PATH;/*** @Author: zhangchenglong06* @Date: 2023/2/9* @Description:*/
public class Directories {static Path test = Paths.get(CURRENT_BASE_PATH, "test");static String sep = FileSystems.getDefault().getSeparator();static List<String> parts = Arrays.asList("foo", "bar", "baz", "bag");static Path makeVariant() {// 移動(dòng)指定列表的元素 distance 位// 例如 [1, 2, 3, 4, 5] 執(zhí)行Collections.rotate(list.subList(1,4),1)// 結(jié)果 [1, 4, 3, 4, 5]Collections.rotate(parts, 1);return Paths.get(CURRENT_BASE_PATH, "test", String.join(sep, parts));}static void refreshTestDir() throws IOException {// 如果文件存在則刪除,否則創(chuàng)建目錄if (Files.exists(test)) {RmDir.rmdir(test);}if (!Files.exists(test)) {Files.createDirectory(test);}}static void populateTestDir() throws IOException {for (int i = 0; i < parts.size(); i++) {Path variant = makeVariant();if (!Files.exists(variant)) {Files.createDirectories(variant);Files.copy(Paths.get(CURRENT_BASE_PATH, "Directories.java"), variant.resolve("File" + i + ".txt"));Files.createTempFile(variant, null, null);}}}public static void main(String[] args) throws IOException {// 刷新測(cè)試目錄refreshTestDir();// 在test路徑下增加Hello.txt文件路徑 并創(chuàng)建此路徑文件Files.createFile(test.resolve("Hello.txt"));// 創(chuàng)建文件Path variant = makeVariant();try {// 創(chuàng)建一級(jí)目錄的函數(shù),當(dāng)創(chuàng)建多級(jí)目錄時(shí)會(huì)拋出文件不存在的異常Files.createDirectory(variant);} catch (Exception e) {System.out.println("Nope, that doesn't work." + e);}populateTestDir();Path tempDir = Files.createTempDirectory(test, "DIR_");Files.createTempFile(tempDir, "pre", ".non");// newDirectoryStream 只顯示指定目錄下的子目錄或文件Files.newDirectoryStream(test).forEach(System.out::println);System.out.println("********************");// walk 可以瀏覽指定目錄下的所有內(nèi)容(目錄樹)Files.walk(test).forEach(System.out::println);}
}
/** 控制臺(tái)* Nope, that doesn't work.java.nio.file.NoSuchFileException: io/src/main/java/com/markus/java/file/test/bag/foo/bar/baz* io/src/main/java/com/markus/java/file/test/DIR_260744175083605522* io/src/main/java/com/markus/java/file/test/foo* io/src/main/java/com/markus/java/file/test/baz* io/src/main/java/com/markus/java/file/test/bar* io/src/main/java/com/markus/java/file/test/bag* io/src/main/java/com/markus/java/file/test/Hello.txt* ********************* io/src/main/java/com/markus/java/file/test* io/src/main/java/com/markus/java/file/test/DIR_260744175083605522* io/src/main/java/com/markus/java/file/test/DIR_260744175083605522/pre7111318949801779914.non* io/src/main/java/com/markus/java/file/test/foo* io/src/main/java/com/markus/java/file/test/foo/bar* io/src/main/java/com/markus/java/file/test/foo/bar/baz* io/src/main/java/com/markus/java/file/test/foo/bar/baz/bag* io/src/main/java/com/markus/java/file/test/foo/bar/baz/bag/File2.txt* io/src/main/java/com/markus/java/file/test/foo/bar/baz/bag/2694156263661518806.tmp* io/src/main/java/com/markus/java/file/test/baz* io/src/main/java/com/markus/java/file/test/baz/bag* io/src/main/java/com/markus/java/file/test/baz/bag/foo* io/src/main/java/com/markus/java/file/test/baz/bag/foo/bar* io/src/main/java/com/markus/java/file/test/baz/bag/foo/bar/File0.txt* io/src/main/java/com/markus/java/file/test/baz/bag/foo/bar/6305328343447758907.tmp* io/src/main/java/com/markus/java/file/test/bar* io/src/main/java/com/markus/java/file/test/bar/baz* io/src/main/java/com/markus/java/file/test/bar/baz/bag* io/src/main/java/com/markus/java/file/test/bar/baz/bag/foo* io/src/main/java/com/markus/java/file/test/bar/baz/bag/foo/File1.txt* io/src/main/java/com/markus/java/file/test/bar/baz/bag/foo/5478658539929705751.tmp* io/src/main/java/com/markus/java/file/test/bag* io/src/main/java/com/markus/java/file/test/bag/foo* io/src/main/java/com/markus/java/file/test/bag/foo/bar* io/src/main/java/com/markus/java/file/test/bag/foo/bar/baz* io/src/main/java/com/markus/java/file/test/bag/foo/bar/baz/File3.txt* io/src/main/java/com/markus/java/file/test/bag/foo/bar/baz/5014150493260271159.tmp* io/src/main/java/com/markus/java/file/test/Hello.txt*/
5、Path監(jiān)聽和查找
FileSystems(文件系統(tǒng))可以獲得兩個(gè)的API:
- WatchService: 監(jiān)聽Path
- TreeMatcher: 查找Path
下面我們看下代碼示例:
- WatchService
package com.markus.java.file;import com.markus.java.file.constant.FileConstant;import java.io.IOException;
import java.nio.file.*;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;/*** @Author: zhangchenglong06* @Date: 2023/2/10* @Description:*/
public class PathWatcher {static Path test = Paths.get(FileConstant.CURRENT_BASE_PATH, "test");static void delTxtFiles() {try {Files.walk(test).filter(f -> f.toString().endsWith(".txt")).forEach(f -> {System.out.println("deleting " + f);try {Files.delete(f);} catch (IOException e) {throw new RuntimeException(e);}});} catch (IOException e) {throw new RuntimeException(e);}}public static void main(String[] args) throws IOException, InterruptedException {// 刷新目錄Directories.refreshTestDir();// 創(chuàng)建目錄下的文件Directories.populateTestDir();Files.createFile(test.resolve("Hello.txt"));WatchService watcher = FileSystems.getDefault().newWatchService();// 只能監(jiān)聽到當(dāng)前目錄下操作,子目錄下的文件操作不會(huì)被監(jiān)聽到test.register(watcher, ENTRY_DELETE);Executors.newSingleThreadScheduledExecutor().schedule(PathWatcher::delTxtFiles, 250, TimeUnit.MILLISECONDS);WatchKey key = watcher.take();for (WatchEvent<?> evt : key.pollEvents()) {System.out.println("evt.context(): " + evt.context() +"\nevt.count(): " + evt.count() +"\nevt.kind(): " + evt.kind());System.exit(0);}}
}
/** 控制臺(tái)* deleting io/src/main/java/com/markus/java/file/test/foo/bar/baz/bag/File3.txt* deleting io/src/main/java/com/markus/java/file/test/baz/bag/foo/bar/File1.txt* deleting io/src/main/java/com/markus/java/file/test/bar/baz/bag/foo/File2.txt* deleting io/src/main/java/com/markus/java/file/test/bag/foo/bar/baz/File0.txt* deleting io/src/main/java/com/markus/java/file/test/Hello.txt* evt.context(): Hello.txt* evt.count(): 1* evt.kind(): ENTRY_DELETE*/
上面的代碼會(huì)有個(gè)缺陷,就是它只能監(jiān)聽到當(dāng)前目錄的操作,而無(wú)法查找當(dāng)前目錄下所有的子目錄的操作行為,如果想監(jiān)聽整個(gè)目錄樹,則必須在整個(gè)樹的每個(gè)子目錄上設(shè)置一個(gè)WatchService
package com.markus.java.file;import com.markus.java.file.constant.FileConstant;import java.io.IOException;
import java.nio.file.*;
import java.util.concurrent.Executors;import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;/*** @Author: zhangchenglong06* @Date: 2023/2/10* @Description:*/
public class TreeWatcher {static void watchDir(Path dir) {try {WatchService watcher = FileSystems.getDefault().newWatchService();dir.register(watcher, ENTRY_DELETE);Executors.newSingleThreadScheduledExecutor().submit(() -> {try {WatchKey key = watcher.take();for (WatchEvent<?> evt : key.pollEvents()) {System.out.println("evt.context(): " + evt.context() +"\nevt.count(): " + evt.count() +"\nevt.kind(): " + evt.kind());System.exit(0);}} catch (InterruptedException e) {return;}});} catch (IOException e) {throw new RuntimeException(e);}}public static void main(String[] args) throws IOException {Directories.refreshTestDir();Directories.populateTestDir();Files.walk(Paths.get(FileConstant.CURRENT_BASE_PATH, "test")).filter(Files::isDirectory).forEach(TreeWatcher::watchDir);PathWatcher.delTxtFiles();}
}
/** 控制臺(tái)* deleting io/src/main/java/com/markus/java/file/test/foo/bar/baz/bag/File3.txt* deleting io/src/main/java/com/markus/java/file/test/baz/bag/foo/bar/File1.txt* deleting io/src/main/java/com/markus/java/file/test/bar/baz/bag/foo/File2.txt* deleting io/src/main/java/com/markus/java/file/test/bag/foo/bar/baz/File0.txt* evt.context(): File1.txt* evt.count(): 1* evt.kind(): ENTRY_DELETE* evt.context(): File0.txt* evt.count(): 1* evt.kind(): ENTRY_DELETE*/
- PathMatcher
package com.markus.java.file;import com.markus.java.file.constant.FileConstant;import java.io.IOException;
import java.nio.file.*;/*** @Author: zhangchenglong06* @Date: 2023/2/10* @Description:*/
public class Find {public static void main(String[] args) throws IOException {Path test = Paths.get(FileConstant.CURRENT_BASE_PATH, "test");Directories.refreshTestDir();Directories.populateTestDir();Files.createDirectory(test.resolve("dir.tmp"));PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:**/*.{tmp,txt}");Files.walk(test).filter(matcher::matches).forEach(System.out::println);System.out.println("*******************");PathMatcher matcher2 = FileSystems.getDefault().getPathMatcher("glob:*.tmp");Files.walk(test).map(Path::getFileName).filter(matcher2::matches).forEach(System.out::println);System.out.println("*******************");Files.walk(test).filter(Files::isRegularFile).map(Path::getFileName).filter(matcher2::matches).forEach(System.out::println);}
}
/** 控制臺(tái)* io/src/main/java/com/markus/java/file/test/foo/bar/baz/bag/File3.txt* io/src/main/java/com/markus/java/file/test/foo/bar/baz/bag/2767500121528410890.tmp* io/src/main/java/com/markus/java/file/test/baz/bag/foo/bar/File1.txt* io/src/main/java/com/markus/java/file/test/baz/bag/foo/bar/5789074899285883862.tmp* io/src/main/java/com/markus/java/file/test/dir.tmp* io/src/main/java/com/markus/java/file/test/bar/baz/bag/foo/File2.txt* io/src/main/java/com/markus/java/file/test/bar/baz/bag/foo/5458649986440731775.tmp* io/src/main/java/com/markus/java/file/test/bag/foo/bar/baz/File0.txt* io/src/main/java/com/markus/java/file/test/bag/foo/bar/baz/5568292198534480479.tmp* ******************** 2767500121528410890.tmp* 5789074899285883862.tmp* dir.tmp* 5458649986440731775.tmp* 5568292198534480479.tmp* ******************** 2767500121528410890.tmp* 5789074899285883862.tmp* 5458649986440731775.tmp* 5568292198534480479.tmp*/
三、組件二:File(文件)
在上面,主要學(xué)習(xí)記錄了對(duì)路徑目錄的操作,現(xiàn)在來(lái)學(xué)習(xí)下如果操作文件本身的內(nèi)容,也就是如何進(jìn)行讀寫文件:
- 通過(guò)Files.readAllLines 可以一次性的讀入整個(gè)文件,生成一個(gè)List<String>。ps:這里不建議一次性讀入大文件,會(huì)撐爆內(nèi)存的
package com.markus.java.file;import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;/*** @author: markus* @date: 2023/2/15 10:39 PM* @Description:* @Blog: https://markuszhang.com* It's my honor to share what I've learned with you!*/
public class ListOfLines {public static void main(String[] args) throws IOException {Files.readAllLines(Paths.get("io/src/main/resources/file_writer.txt")).forEach(System.out::println);}
}
/** 控制臺(tái)* Hello,IO*/
- 通過(guò)Files.write可以將byte數(shù)組或任何實(shí)現(xiàn)了Iterable接口的類的對(duì)象寫入文件
package com.markus.java.file;import com.markus.java.file.constant.FileConstant;import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.Random;/*** @author: markus* @date: 2023/2/16 10:33 PM* @Description:* @Blog: https://markuszhang.com* It's my honor to share what I've learned with you!*/
public class Writing {static Random rand = new Random(47);static final int SIZE = 1000;public static void main(String[] args) throws IOException {// 將字節(jié)寫入一個(gè)文件byte[] bytes = new byte[SIZE];rand.nextBytes(bytes);
// Files.write(Paths.get(FileConstant.CURRENT_BASE_PATH, "bytes.txt"), bytes, Charset.forName("charset"));Files.write(Paths.get(FileConstant.CURRENT_BASE_PATH, "bytes.txt"), bytes);System.out.println("bytes.txt: " + Files.size(Paths.get(FileConstant.CURRENT_BASE_PATH, "bytes.txt")));// 將實(shí)現(xiàn)了Iterable接口的類的對(duì)象寫入一個(gè)文件List<String> lines = Files.readAllLines(Paths.get("io/src/main/resources/file_writer.txt"));Files.write(Paths.get("io/src/main/resources/file_writer.txt"), lines);System.out.println("file_writer.txt: " + Files.size(Paths.get("io/src/main/resources/file_writer.txt")));}
}
/*** 控制臺(tái)* bytes.txt: 1000* file_writer.txt: 9*/
- 通過(guò)Files.lines可以很方便的將一個(gè)文件變?yōu)橐粋€(gè)由行組成的Stream,這樣可以應(yīng)對(duì)當(dāng)文件非常大,而我們只需要文件的一部分時(shí),進(jìn)行讀取,而非全部讀入內(nèi)存當(dāng)中
package com.markus.java.file;import com.markus.java.file.constant.FileConstant;import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;/*** @author: markus* @date: 2023/2/16 10:47 PM* @Description:* @Blog: https://markuszhang.com* It's my honor to share what I've learned with you!*/
public class ReadLineStream {public static void main(String[] args) throws IOException {Files.lines(Paths.get(FileConstant.CURRENT_BASE_PATH, "PathInfo.java")).skip(13).findFirst().ifPresent(System.out::println);}
}
/** 控制臺(tái)* * @Author: zhangchenglong06*/
- 通過(guò)Files.lines我們也可以實(shí)現(xiàn)由行組成的輸入流來(lái)在流中完成讀取、處理、寫入等操作
package com.markus.java.file;import com.markus.java.file.constant.FileConstant;import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Stream;/*** @author: markus* @date: 2023/2/16 10:52 PM* @Description:* @Blog: https://markuszhang.com* It's my honor to share what I've learned with you!*/
public class StreamInAndOut {public static void main(String[] args) {try (Stream<String> input = Files.lines(Paths.get(FileConstant.CURRENT_BASE_PATH, "StreamInAndOut.java"));PrintWriter writer = new PrintWriter(FileConstant.CURRENT_BASE_PATH + "StreamInAndOut.txt");) {input.map(String::toUpperCase).forEachOrdered(writer::println);} catch (IOException e) {e.printStackTrace();}}
}
四、全文總結(jié)
本文記錄了基于Path、Paths、File、Files等抽象對(duì)文件、目錄相關(guān)的操作,摒棄了傳統(tǒng)的Java I/O操作類,它使得我們對(duì)文件等的操作更加簡(jiǎn)單,它屏蔽了用戶與底層的交互,也使得代碼可以跨平臺(tái)運(yùn)行。