java 接受流文件_java流与文件——操作文件

【0】README

0.1) 本文描述转自 core java volume 2, 旨在理解 java流与文件——操作文件 的相关知识;

0.2) for source code, please visit https://github.com/pacosonTang/core-java-volume/blob/master/coreJavaAdvanced/chapter1/FileAndPathTest.java)

【1】Path

1.1)Path: 表示的是一个目录名序列, 其后还可以跟一个文件名;路径中的第一个部件可以是跟部件, 例如 / 或 C:/ , 而有序访问的根部件,取决于文件系统;(干货——Path类定义)

1.1.1)以根目录开始的是绝对路径,否则就是相对路径;如,

Path absolute = Paths.get(“/home”, “cay”);

Path relative = Paths.get(“myprog”, “cay”);

1.1.2) 静态的 Paths.get 方法: 接受一个或多个字符串, 并将它们用默认文件系统的路径分隔符连接起来;

1.1.3)get方法: 可以获取包含多个部件构成的单个字符串, 如, 可以像下面这样从配置文件中读取路径:

String baseDir = props.getProperty(“base.dir”);

Path basePath = Paths.get(baseDir);

8378b6f1739755504ed21ee995ec40fc.png

Attention)

A1)路径不必对应着某个实际存在的文件, 他仅仅只是一个抽象的名字序列;

A2)当你想要创建文件时, 首先要创建一个路径,然后才调用方法去创建对应的文件;

1.2)组合或解析路径是司空见惯的操作,调用 p.resolve(q) 将按照下列规则返回一个路径: (干货——p后面跟着q)

1.2.1)如果 q 是绝对路径, 则结果就是q;

1.2.2)否则,根据文件系统的规则, 将p 后面跟着q 作为结果;

1.2.3) resolve 方法有一种快捷方式,它接收一个字符串而不是路径:

Path workPath = basePath.resolve(“work”);

1.2.4)还有一个 方法: resolveSibling

它通过解析指定路径的父路径产生其兄弟路径, 例如, 如果workPath 是 /opt/myapp/work, 那么下面的调用

Path tempPath = workPath.resolveSibling(“temp”) 将创建 /opt/myapp/temp; (干货——创建兄弟路径)

1.2.5)resolve的对立面是 relative: 即调用 p.relativeze(r) 将产生路径q, 对q进行解锁产生r;

1.2.6)normalize 方法:移除所有冗余的 . 和 .. 部件(或者文件系统认为冗余的所有部件);

如规范化 /home/cay/../fred/./ myprog 将产生 /home/fred/myprog

3662a15a755672d8e6d1abdb43041432.png

1.2.7)toAbsolutePath 方法: 将产生给定路径的绝对路径, 该绝对路径从根部件开始;

1.2.8) Path类有许多方法用来将路径断开以及和其它路径进行组合。如:

Path p = Paths.get(“/home”, “myprog.properties”);

Path parent = p.getParent();

Path file = p.getFilename();

Path root = p.getRoot();

Attention) 你可能需要与遗留系统的API 交互, 它们使用的是 File 类而不是 Path 类。 Path类有一个toFile 方法, 而 File 类也有一个 toPath 方法;

【2】读写文件

2.1)Files 类可以使得普通文件操作变得快捷;

2.1.1)用下面的方式很容易的读取文件的所有内容:

byte[] bytes = Files.readAllBytes(path);

2.1.2)如果想将文件当做字符串输入, 则:

String content = enw String(bytes, charset);

2.1.3)如果希望 将文件当做行序列输入, 则:

List lines = Files.readAllLines(path, charset);

2.1.4)相反地, 如果希望写出一个字符串到文件中, 则:

Files.write(path, content.getBytes(charset));

4219aab0461f0c3a08d5afd6aecd56f5.png

2.1.5)向指定文件追加内容,则:

Files.write(path, content.getBytes(charset), StandardOpoenOption.APPEND);

2.1.6)还可以用下面的语句将一行集合写出到文件中:

Files.write(path, lines);

677019fe7db82e5e9435a0bb88659c8f.png

2.1.7) 如果要处理的文件长度过大, 或者是二进制文件, 那么还是应该使用所熟悉的流或者读入器/ 写出器;

InputStream is = Files.newInputStream(path);

OutputStream os = Files.newOutputStream(path);

Reader reader = Files.newBufferedReader(path, charset);

Writer writer = Files.newBufferedWriter(path, charset);

2.1.8)总结: 这些便捷方法可以将你从处理 FileInputStream, FileInputStream, BufferedReader 和 BufferedWriter 的繁复操作中解脱出来;

【3】复制、移动和删除文件

3.1)复制文件: Files.copy(fromPath, toPath);

3.2)移动文件 (复制并删除源文件): Files.move(frompath, topath);

3.2.1)如果目标路径已经存在,那么复制或移动将失败;

3.2.2)如果想要覆盖已有的目标路径, 可以使用 REPLACE_EXISTING 选项;

3.2.3)如果想要复制文件的属性, 可以使用 COPY_ATTRIBUTES ;

3.2.4)也可以同时使用者两个选项:

Files.copy(fromPath, toPath, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES);

3.2.5)可以将移动操作定义为 原子性的(要么全部成功, 要么就不成功)

Files.move(fromPath, toPath, StandardCopyOption.ATOMIC_MOVE);

3.2.6)最后删除文件,调用:

Files.delete(path);

3.2.7)如果要删除的文件不存在, delete 方法就会抛出异常;使用 deleteIfExists 不会抛出异常,

boolean deleted = Files.deleteIfExists(path); 该方法 deleteIfExists 还可以用来移除空目录;

0e0f2ddbbbf40ac29f4829c233dcf70b.png

【4】 创建文件和目录

4.1)创建目录: Files.createDirectory(path);

4.2)创建中间目录: Files.createDirectories(path); (迭代创建目录)

4.2.1)创建空文件: Files.createFile(path)

4.2.2)有些便捷方法用来在给定位置或系统指定位置创建临时文件或 临时目录:

Path newPath = FIles.createTempFile(dir, prefix, suffix);

Path newPath = FIles.createTempFile( prefix, suffix);

Path newPath = FIles.createTempFile(dir, prefix);

Path newPath = FIles.createTempFile(prefix);

其中,dir 是一个Paht对象,prefix 和 suffix 是可以为 null 的字符串;例如,调用 Files.createTempFile(null, “.txt”) 可能返回一个像 /tmp/2345646464646464.txt这样的路径;

496e9947d252c322443c93eed58c6959.png

【5】 获取文件信息

5.1)下面的静态方法都将返回一个boolean值, 表示检查路径的某个属性的结果:

exists + isHidden + isReadable + isWritable + isExecutable + isRegularFile + isDirectory + isSymbolicLink

5.2)size 方法将返回文件的字节数:

long size = Files.size(path);

5.3)getOwner: 将文件的所有者作为 java.nio.file.attribute.UserPrincipal 的一个实例返回;

5.4)所有的文件系统都会报告一个基本属性集, 它们被封装在 BasicFileAttributes 接口中, 这些属性与上述信息有部分重叠。基本文件属性包括:

5.4.1)创建文件, 最后一次访问以及最后一次修改时间;

5.4.2)文件时常规文件, 目录还是符号链接, 或者都不是;

5.4.3)文件大小;

5.4.4)文件主键, 这是某种类的对象, 具体所属类与文件系统相关, 有可能是文件的唯一标识符,也有可能不是;

5.4.5)要获取这些属性,调用

BasicFileAttributes attributes = files.readAttributes(path, BasicFileAttributes.class);

5.5) 如果你了解到用户的文件系统兼容 POSIX, 可以获取一个 PosiXFileAttributes 实例:

PosiXFileAttributes attributes = files.readAttributes(path, PosiXFileAttributes.class);

然后从中找到组拥有者, 拥有者,组,以及访问权限;

9ff04bfe7b71941146ce57a2e26a3ada.png

【6】 迭代目录中的文件

6.1)problem+solution

6.1.1)problem: 旧File 类有一个方法,用来获取由一个目录的所有文件构成的数组, 当目录包含大量的文件时,方法性能非常低;

6.1.2)solution: File类设计了一个方法, 产生一个 Iterable 对象, 如:

try(DirectoryStream entries = Files.newDirectoryStream(dir))

{

for(Path entry : entries)

process entries

}

6.1.3)try 语句块用来确保目录流可以被正确关闭。访问目录中的项并没有具体的顺序, 可以用 glob 模式来过滤:(干货——带资源的try语句块)

try(DirectoryStream entries = Files.newDirectoryStream(dir, “*.java”));

accafc3e5788d0e240e094da22db7329.png

Warning)如果使用 Windows 的 glob 语法, 则必须对反斜杠转移两次:一次为 glob 语法转义, 一次为java 字符串转义:Files.newDirectoryStream(dir, “C:\\”)

27076a8014df9d30cda559b0773493a9.png

6.2)如果想要访问某个目录的子孙成员, 转而调用 walkFileTree 方法, 并向其传递一个 FileVisitor 类型的对象, 这个对象会得到下面通知:

6.2.1)在遇到一个文件或目录时: FileVisitResult visitFile(T path, BasicFileAttributes attrs)

6.2.2) 在一个目录被处理前: FileVisitResult preVisitFile(T dir, IOException ex)

6.2.3) 在一个目录被处理后: FileVisitResult postVisitFile(T dir, IOException ex)

6.2.4) 在试图访问文件或目录时发生错误, 例如没有权限打开目录: FileVisitResult visitFileFailed(path, IOException)

6.3) 对上述每种情况, 都可以指定是否希望执行下面的操作:

6.3.1)继续访问下一个文件: FileVisitResult.CONTINUE;

6.3.2)继续访问,但不在访问这个目录下的任何项了: FileVisitResult.SKIP_SUBTREE;

6.3.3)继续访问, 但是不在访问这个文件的兄弟文了: FileVisitResult.SKIP_SIBLINES;

6.3.4)终止访问: FileVisitResult.TRIMINATE ;

6.4) 当有任何方法抛出异常时, 就会终止访问, 而这个异常会从 walkFileTree 方法中抛出;

Attention) FileVisitor 接口是泛化类型, 但是你也太可能会使用 除开 FileVisit 之外的东西; walkFileTree 方法可以接收 FileVisitor

【7】 ZIP 文件系统

7.1)建立一个文件系统, 包含 ZIP 文档中的所有文件;

FileSystem fs = FileSystems.newFIleSystem(Paths.get(zipname), null);

7.1.1)如果知道文件名,从ZIP 文档中复制出这个文件就变得很容易:

Files.copy(fs.getPath(sourceName), targetPath);

7.1.2)要列出ZIP 文档中的所有文件, 可以遍历文件树:

FileSystem fs = FileSystems.newFIleSystem(Paths.get(zipname), null)

Files.walkFileTree(fs,.getPath("/"), new SimpleFileVisitor()

{

public FileVisitResult visitFile(Path file , BasicFIleAttributes attrs)

{

println(file);

return FileVisitResult.CONTINUE;

}

}

)

5e43469d700e296ff123cd6e6e1fc577.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值