Java I/O之文件系统
一、全文概览
在学习文件系统之前,需要了解下Java在I/O上的发展史:在Java7之前,打开和读取文件需要编写特别笨拙的代码,涉及到很多的InputStream、OutputStream等组合起来使用,每次在使用时或许都需要查一下文档才能记得如何打开一个文件;而在Java 7面世后,这些被人诟病的设计得到了巨大的改进,这些新元素被打包放在了java.nio.file之下。这个包对Java对文件的操作提升到了可以与其他编程语言媲美的程度。
本篇文章就主要学习记录下操作文件的两个基本组件:
- 文件或目录的路径-Path
- 文件本身-File
二、组件一:Path(路径)
1、Path简介
Path对象代表的是一个文件或目录的路径,它是在不同的操作系统和文件系统之上的抽象。它的目的是,我们不必要注意底层的操作系统,我们的代码不需要重写就能在不同的操作系统上工作 —来自:《OnJava-基础篇》
2、Path创建
介绍完Path出现的目的后,我们再来看下如果获取Path。正是java.nio.file.Paths类下重载的static get方法,这个方法的参数可以是接受一个String序列(也就是全路径,系统能够找到的);也可以是一个统一的资源标识符(URI),然后将其转换为Path
下面是对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));// 是否是常规文件,也就是我们常规意义上的文件,例如.txt .png等,而非目录show("RegularFile: ", Files.isRegularFile(path));// 是否是目录show("Directory: ", Files.isDirectory(path));// 展示绝对路径show("Absolute: ", path.toAbsolutePath());// 展示文件名(最后一级)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对象路径的各个部分,例如/Users/zhangchenglong/IdeaProjects/OnJava8-Examples/io/src/main/java/com/markus/java中每个//之间的内容都是一个片段
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*/
我们还可以对片段进行添加和删除,需要学习api如下:
- Path#relativize : 在路径首部删除基准路径形成新的路径
- Path#normalize : 删除冗余名称元素的路径
- Path#resolve : 在Path对象后面增加路径片段
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 删除基准路径* resolve 增加路径*/
public class AddAndSubtractPaths {static Path base = Paths.get("..", "..", "..").toAbsolutePath().normalize();static void show(int id, Path result) {if (result.isAbsolute()) {// result 在 路径首部删除base基准路径形成新的路径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/../ 直接删除两个元素即可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工具类包含了操作目录和文件所需要的大部分操作,但其中缺乏删除目录树的工具方法,这里我们做个删除目录树工具的练习
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>() {/*** 在这个目录下的每个文件上运行* @param file* @param attrs* @return* @throws IOException*/@Overridepublic FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {Files.delete(file);return FileVisitResult.CONTINUE;}/*** 先进入当前目录下的文件和目录(包括所有的子目录),最后在当前目录上运行* @param dir* @param exc* @return* @throws IOException*/@Overridepublic FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {Files.delete(dir);return FileVisitResult.CONTINUE;}/*** 先在当前目录上运行,然后进入这个目录下的文件和目录* @param dir* @param attrs* @return* @throws IOException*/@Overridepublic FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {return super.preVisitDirectory(dir, attrs);}/*** 当文件无法访问时调用* @param file* @param exc* @return* @throws IOException*/@Overridepublic FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {return super.visitFileFailed(file, exc);}});}
}
下面来检验下删除工具的有效性
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() {// 移动指定列表的元素 distance 位// 例如 [1, 2, 3, 4, 5] 执行Collections.rotate(list.subList(1,4),1)// 结果 [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 {// 如果文件存在则删除,否则创建目录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 {// 刷新测试目录refreshTestDir();// 在test路径下增加Hello.txt文件路径 并创建此路径文件Files.createFile(test.resolve("Hello.txt"));// 创建文件Path variant = makeVariant();try {// 创建一级目录的函数,当创建多级目录时会抛出文件不存在的异常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 可以浏览指定目录下的所有内容(目录树)Files.walk(test).forEach(System.out::println);}
}
/** 控制台* 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监听和查找
FileSystems(文件系统)可以获得两个的API:
- WatchService: 监听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();// 创建目录下的文件Directories.populateTestDir();Files.createFile(test.resolve("Hello.txt"));WatchService watcher = FileSystems.getDefault().newWatchService();// 只能监听到当前目录下操作,子目录下的文件操作不会被监听到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);}}
}
/** 控制台* 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*/
上面的代码会有个缺陷,就是它只能监听到当前目录的操作,而无法查找当前目录下所有的子目录的操作行为,如果想监听整个目录树,则必须在整个树的每个子目录上设置一个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();}
}
/** 控制台* 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);}
}
/** 控制台* 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(文件)
在上面,主要学习记录了对路径目录的操作,现在来学习下如果操作文件本身的内容,也就是如何进行读写文件:
- 通过Files.readAllLines 可以一次性的读入整个文件,生成一个List<String>。ps:这里不建议一次性读入大文件,会撑爆内存的
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);}
}
/** 控制台* Hello,IO*/
- 通过Files.write可以将byte数组或任何实现了Iterable接口的类的对象写入文件
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 {// 将字节写入一个文件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")));// 将实现了Iterable接口的类的对象写入一个文件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")));}
}
/*** 控制台* bytes.txt: 1000* file_writer.txt: 9*/
- 通过Files.lines可以很方便的将一个文件变为一个由行组成的Stream,这样可以应对当文件非常大,而我们只需要文件的一部分时,进行读取,而非全部读入内存当中
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);}
}
/** 控制台* * @Author: zhangchenglong06*/
- 通过Files.lines我们也可以实现由行组成的输入流来在流中完成读取、处理、写入等操作
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();}}
}
四、全文总结
本文记录了基于Path、Paths、File、Files等抽象对文件、目录相关的操作,摒弃了传统的Java I/O操作类,它使得我们对文件等的操作更加简单,它屏蔽了用户与底层的交互,也使得代码可以跨平台运行。
相关文章:
Java I/O之文件系统
一、全文概览 在学习文件系统之前,需要了解下Java在I/O上的发展史:在Java7之前,打开和读取文件需要编写特别笨拙的代码,涉及到很多的InputStream、OutputStream等组合起来使用,每次在使用时或许都需要查一下文档才能记…...
Mysql元数据获取方法(information_schema绕过方法)
前提:如果waf或其它过滤了information_schema关键字,那我们该如何获取元数据呢?能够代替information_schema的有:sys.schema_auto_increment_columnssys.schema_table_statistics_with_bufferx$schema_table_statistics_with_buff…...
Eclipse快捷键
* 1.补全代码的声明:alt /* 2.快速修复: ctrl 1 * 3.批量导包:ctrl shift o* 4.使用单行注释:ctrl /* 5.使用多行注释: ctrl shift / * 6.取消多行注释:ctrl shift \* 7.复制指定行的代码:ctrl a…...
java ssm自习室选座预约系统开发springmvc
人工管理显然已无法应对时代的变化,而自习室选座预约系统开发能很好地解决这一问题,既能提高人力物力,又能提高预约选座的知名度,取代人工管理是必然趋势。 本自习室选座预约系统开发以SSM作为框架,JSP技术,…...
分享我从功能测试转型到测试开发的真实故事
由于这段时间我面试了很多家公司,也经历了之前公司的不愉快。所以我想写一篇文章来分享一下自己的面试体会。希望能对我在之后的工作或者面试中有一些帮助,也希望能帮助到正在找工作的你。 找工作 我们总是草率地进入一个自己不了解的公司工作…...
TypeScript快速入门———(二)TypeScript常用类型
文章目录概述1 类型注解2 常用基础类型概述3.原始类型4 数组类型5 类型别名6.函数类型7 对象类型8 接口9 元组10 类型推论11 类型断言12 字面量类型13 枚举14 any 类型15 typeof概述 TypeScript 是 JS 的超集,TS 提供了 JS 的所有功能,并且额外的增加了…...
Mac M1 使用Centos8➕VMware Fusion进行静态网络配置
大部分的流程网络上面都有当我们已经下载好mac m1版的Centos8链接: https://pan.baidu.com/s/1UTl4Lo-_c17s-PDj3dA6kA 提取码: 7xh2 和VMware Fusionhttps://www.vmware.com/cn/products/fusion.html之后就可以进行安装了在导入过后 记得将硬盘和内存都设置好了 记得在关机状态…...
RadGraph: Extracting Clinical Entities and Relations from Radiology Reports代码
文章来源:NeurIPS 文章类别:IE(Information Extraction) RadGraph主要基于dygie,主要文件为inference.py。 inference.py: 1、get_file_list(data_path) def get_file_list(path):file_list [item for item in glob.glob(f&q…...
13. OPenGL与QT界面元素交互控制图形渲染
1. 说明: 前面文章中讲到的 OPenGL 渲染都是在页面加载完成即立刻渲染的,如果向控制图形渲染的时间,可以在QT界面中添加一些元素来进行控制。此时需要用到OPenGL当中的makeCurrent(),update(),doneCurrent()函数。 效果展示: ope…...
高通平台开发系列讲解(USB篇)libuvc详解
文章目录 一、什么是UVC二、UVC拓扑结构三、libuvc的预览时序图沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇文章将介绍libuvc。 一、什么是UVC UVC,全称为:USB video(device) class。 UVC是微软与另外几家设备厂商联合推出的为USB视频捕获设备定义的协议标…...
ICC2:set_route_opt_target_endpoints
route_opt阶段通过指定endpoint/driver pin list的方式执行incremental优化。 set_route_opt_target_endpoints [-setup_endpoints file] [-setup_endpoints_collection pin_list] [-hold_endpoints file] [-hold_endpoints_collection pin_list] [-ldrc_objects fil…...
5、小程序面试题
1, 小程序页面有哪些生命周期函数onLoad: 页面加载onReady: 页面初次渲染完成onShow: 页面显示onHide: 页面隐藏onUnload: 页面卸载2, 一页小程序页面有哪些文件组成,分别有什么作用.wxml: 使用微信框架设计的一套组件构建页面结构.wxss: 用于设置页面样式, 和css基本一致.js :…...
Java特殊操作流
6 特殊操作流 6.1 标注输入输出流 System类中有两个静态的成员变量: public static final InputStream in:标准输入流,通常该流对应于键盘输入或由主机环境或用户指定的另一个输入源public static final PrintStream out:标准输…...
如何用SCRM销售管理系统管理销售和做销售管理
每一家企业都在找适合自己公司的销售管理方法,实现销售目标和努力提高业绩。 我们常说,做好销售管理有很多路径和方法,但我们不知道从哪里开始?每个阶段我们该怎么办?如何有效管理销售团队?好的企企业微信…...
分享117个HTML婚纱模板,总有一款适合您
分享117个HTML婚纱模板,总有一款适合您 117个HTML婚纱模板下载链接:https://pan.baidu.com/s/1cC3I5cfh91-KmQj4nfSoPA?pwd9hod 提取码:9hod Python采集代码下载链接:采集代码.zip - 蓝奏云 import os import shutil import …...
VIVADO2022 sdk 工程创建流程
正点原子uart历程复现 create block design(起名 为System) -> open block design -> 号/IP catalog 中搜索zynq 双击打开, 将和pl相关的时钟都干掉 再auto 布线一下 把herarchy中的sources 中的system.bd右键、 无脑下一步导出 如…...
【MyBatis】源码学习 02 - Java 元注解以及 MyBatis @Param 注解分析
文章目录前言参考目录学习笔记1、Java 注解1.1、Java 元注解1.2、Java ElementType 枚举值1.3、自定义注解2、Param 注解分析2.1、Param 注解2.2、测试方法2.3、流程分析(重点:ParamNameResolver)前言 本文内容对应的是书本第 7 章的内容&am…...
贪心算法-蓝桥杯
一、贪心算法的优缺点优点:1.容易理解:生活常见。2.操作简单:在每一步都选局部最优。3.效率高: 复杂度常常是O(1)的。缺点:1.局部最优不一定是全局最优。二、例子: 最少硬币问题硬币面值1、2、5。支付13元,要求硬币数量最少。贪心法: (1) 5元…...
zookeeper 复习 ---- chapter03
zookeeper 复习 ---- chapter03如何创建 zookeeper 对象 要求: 1:知道这几个构造参数 2:知道每一个参数的含义 ZooKeeper(String connectString, int sessionTimeout, Watcher watcher) ZooKeeper(String connectString, int sessionTimeout…...
1.PostgreSQL
文章目录LIMITWITH 和RECURSIVEPostgreSQL 约束PostgreSQL AUTO INCREMENT(自动增长)PostgreSQL PRIVILEGES(权限)GRANT语法LIMIT SELECT * FROM COMPANY LIMIT 3 OFFSET 2;WITH 和RECURSIVE WITH RECURSIVE t(a,b) AS (VALUES (…...
【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
Day131 | 灵神 | 回溯算法 | 子集型 子集
Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣(LeetCode) 思路: 笔者写过很多次这道题了,不想写题解了,大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...
iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...
2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...
Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...
ip子接口配置及删除
配置永久生效的子接口,2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...
安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖
在Vuzix M400 AR智能眼镜的助力下,卢森堡罗伯特舒曼医院(the Robert Schuman Hospitals, HRS)凭借在无菌制剂生产流程中引入增强现实技术(AR)创新项目,荣获了2024年6月7日由卢森堡医院药剂师协会࿰…...
