Java 中文官方教程 2022 版(八)(2)

简介: Java 中文官方教程 2022 版(八)

Java 中文官方教程 2022 版(八)(1)https://developer.aliyun.com/article/1486329

什么是路径?(以及其他文件系统事实)

原文:docs.oracle.com/javase/tutorial/essential/io/path.html

文件系统在某种介质上存储和组织文件,通常是一个或多个硬盘,以便可以轻松检索文件。今天大多数使用的文件系统将文件存储在树(或分层)结构中。树的顶部是一个(或多个)根节点。在根节点下面,有文件和目录(在 Microsoft Windows 中称为文件夹)。每个目录可以包含文件和子目录,子目录又可以包含文件和子目录,依此类推,可能深入到几乎无限的深度。

本节涵盖以下内容:

  • 什么是路径?
  • 相对还是绝对?
  • 符号链接

什么是路径?

以下图显示了包含单个根节点的示例目录树。Microsoft Windows 支持多个根节点。每个根节点映射到一个卷,例如C:\D:\。Solaris OS 支持单个根节点,用斜杠字符/表示。

示例目录结构

文件通过其在文件系统中的路径来标识,从根节点开始。例如,在前面的图中,Solaris OS 中的statusReport文件由以下表示:

/home/sally/statusReport

在 Microsoft Windows 中,statusReport由以下表示:

C:\home\sally\statusReport

用于分隔目录名称的字符(也称为分隔符)特定于文件系统:Solaris OS 使用正斜杠(/),而 Microsoft Windows 使用反斜杠(\)。

相对还是绝对?

路径可以是相对的或绝对的。绝对路径始终包含根元素和完整的目录列表,以定位文件。例如,/home/sally/statusReport是一个绝对路径。定位文件所需的所有信息都包含在路径字符串中。

相对路径需要与另一个路径结合才能访问文件。例如,joe/foo是一个相对路径。没有更多信息,程序无法可靠地定位文件系统中的joe/foo目录。

符号链接

文件系统对象通常是目录或文件。每个人都熟悉这些对象。但是一些文件系统也支持符号链接的概念。符号链接也称为symlinksoft link

符号链接是一个特殊文件,用作指向另一个文件的引用。在大多数情况下,符号链接对应用程序是透明的,对符号链接的操作会自动重定向到链接的目标。(被指向的文件或目录称为链接的目标。)例外情况是当符号链接被删除或重命名时,链接本身被删除或重命名,而不是链接的目标。

在下图中,对用户来说,logFile看起来像是一个常规文件,但实际上它是指向dir/logs/HomeLogFile的符号链接。HomeLogFile是链接的目标。

符号链接示例。

对用户来说,符号链接通常是透明的。读取或写入符号链接与读取或写入任何其他文件或目录相同。

解析链接这个短语意味着用文件系统中的实际位置替换符号链接。在这个例子中,解析logFile会得到dir/logs/HomeLogFile

在现实场景中,大多数文件系统广泛使用符号链接。偶尔,粗心创建的符号链接可能会导致循环引用。循环引用发生在链接的目标指向原始链接的情况下。循环引用可能是间接的:目录a指向目录b,后者指向目录c,后者包含一个子目录指向目录a。当程序递归遍历目录结构时,循环引用可能会造成混乱。然而,这种情况已经考虑到,不会导致程序无限循环。

下一页将讨论 Java 编程语言中文件 I/O 支持的核心,即Path类。

Path 类

原文:docs.oracle.com/javase/tutorial/essential/io/pathClass.html

Path类是 Java SE 7 版本中引入的主要入口点之一,属于java.nio.file包。如果您的应用程序使用文件 I/O,您将希望了解此类的强大功能。


版本说明: 如果您有使用java.io.File的 JDK7 之前的代码,您仍然可以通过使用File.toPath方法来利用Path类的功能。有关更多信息,请参阅旧版文件 I/O 代码。


正如其名称所示,Path类是文件系统中路径的程序表示。Path对象包含用于构建路径的文件名和目录列表,并用于检查、定位和操作文件。

一个Path实例反映了底层平台。在 Solaris 操作系统中,Path使用 Solaris 语法(/home/joe/foo),而在 Microsoft Windows 中,Path使用 Windows 语法(C:\home\joe\foo)。Path不是系统独立的。你不能比较来自 Solaris 文件系统的Path并期望它与来自 Windows 文件系统的Path匹配,即使目录结构相同,两个实例都定位到相同的相对文件。

Path对应的文件或目录可能不存在。您可以创建一个Path实例并以各种方式操作它:您可以附加到它,提取它的部分,将其与另一个路径进行比较。在适当的时候,您可以使用Files类中的方法来检查与Path对应的文件的存在性,创建文件,打开文件,删除文件,更改其权限等。

下一页将详细讨论Path类。

Path 操作

原文:docs.oracle.com/javase/tutorial/essential/io/pathOps.html

Path类包括各种方法,可用于获取有关路径的信息,访问路径的元素,将路径转换为其他形式或提取路径的部分。还有用于匹配路径字符串的方法以及用于删除路径中冗余的方法。本课程介绍了这些Path方法,有时称为语法操作,因为它们作用于路径本身,而不访问文件系统。

本节涵盖以下内容:

  • 创建一个 Path
  • 检索有关 Path 的信息
  • 从 Path 中删除冗余
  • 转换 Path
  • 连接两个路径
  • 在两个路径之间创建路径
  • 比较两个路径

创建一个 Path

一个Path实例包含用于指定文件或目录位置的信息。在定义时,Path会提供一系列一个或多个名称。可能包括根元素或文件名,但都不是必需的。Path可能仅包含单个目录或文件名。

您可以通过使用Paths(注意复数形式)辅助类中的以下get方法之一轻松创建Path对象:

Path p1 = Paths.get("/tmp/foo");
Path p2 = Paths.get(args[0]);
Path p3 = Paths.get(URI.create("file:///Users/joe/FileTest.java"));

Paths.get方法是以下代码的简写:

Path p4 = FileSystems.getDefault().getPath("/users/sally");

以下示例假定您的主目录是/u/joe,则创建/u/joe/logs/foo.log,或者如果您在 Windows 上,则为C:\joe\logs\foo.log

Path p5 = Paths.get(System.getProperty("user.home"),"logs", "foo.log");

检索有关路径的信息

你可以将Path看作将这些名称元素存储为序列。目录结构中最高的元素位于索引 0。目录结构中最低的元素位于索引[n-1],其中nPath中名称元素的数量。可用于使用这些索引检索单个元素或Path的子序列的方法。

本课程中的示例使用以下目录结构。

示例目录结构

以下代码片段定义了一个Path实例,然后调用了几种方法以获取有关路径的信息:

// None of these methods requires that the file corresponding
// to the Path exists.
// Microsoft Windows syntax
Path path = Paths.get("C:\\home\\joe\\foo");
// Solaris syntax
Path path = Paths.get("/home/joe/foo");
System.out.format("toString: %s%n", path.toString());
System.out.format("getFileName: %s%n", path.getFileName());
System.out.format("getName(0): %s%n", path.getName(0));
System.out.format("getNameCount: %d%n", path.getNameCount());
System.out.format("subpath(0,2): %s%n", path.subpath(0,2));
System.out.format("getParent: %s%n", path.getParent());
System.out.format("getRoot: %s%n", path.getRoot());

这是 Windows 和 Solaris OS 的输出:

调用的方法 Solaris OS 中的返回 Microsoft Windows 中的返回 注释
toString /home/joe/foo C:\home\joe\foo 返回Path的字符串表示。如果路径是使用Filesystems.getDefault().getPath(String)Paths.get(后者是getPath的便利方法)创建的,则该方法会执行轻微的语法清理。例如,在 UNIX 操作系统中,它将修正输入字符串//home/joe/foo/home/joe/foo
getFileName foo foo 返回文件名或名称元素序列的最后一个元素。
getName(0) home home 返回与指定索引对应的路径元素。第 0 个元素是最靠近根的路径元素。
getNameCount 3 3 返回路径中的元素数量。
subpath(0,2) home/joe home\joe 返回Path的子序列(不包括根元素),由开始和结束索引指定。
getParent /home/joe \home\joe 返回父目录的路径。
getRoot / C:\ 返回路径的根。

前面的示例显示了绝对路径的输出。在以下示例中,指定了相对路径:

// Solaris syntax
Path path = Paths.get("sally/bar");
or
// Microsoft Windows syntax
Path path = Paths.get("sally\\bar");

以下是 Windows 和 Solaris OS 的输出:

调用的方法 Solaris OS 中返回 Microsoft Windows 中返回
toString sally/bar sally\bar
getFileName bar bar
getName(0) sally sally
getNameCount 2 2
subpath(0,1) sally sally
getParent sally sally
getRoot null null

从路径中删除冗余

许多文件系统使用“.”符号表示当前目录,“…”表示父目录。您可能会遇到路径包含冗余目录信息的情况。也许服务器配置为将其日志文件保存在“/dir/logs/.”目录中,您希望从路径中删除末尾的“/.`”符号。

以下示例都包含冗余:

/home/./joe/foo
/home/sally/../joe/foo

normalize方法会删除任何冗余元素,包括任何“.”或“directory/…”出现。前面两个示例都会规范化为/home/joe/foo`。

值得注意的是,normalize在清理路径时不会检查文件系统。这是一个纯语法操作。在第二个示例中,如果sally是一个符号链接,删除sally/..可能导致Path不再定位到预期的文件。

为了清理路径并确保结果定位到正确的文件,您可以使用toRealPath方法。该方法在下一节转换路径中描述。

转换路径

您可以使用三种方法来转换Path。如果需要将路径转换为可以从浏览器打开的字符串,可以使用toUri。例如:

Path p1 = Paths.get("/home/logfile");
// Result is file:///home/logfile
System.out.format("%s%n", p1.toUri());

toAbsolutePath方法将路径转换为绝对路径。如果传入的路径已经是绝对路径,则返回相同的Path对象。在处理用户输入的文件名时,toAbsolutePath方法非常有帮助。例如:

public class FileTest {
    public static void main(String[] args) {
        if (args.length < 1) {
            System.out.println("usage: FileTest file");
            System.exit(-1);
        }
        // Converts the input string to a Path object.
        Path inputPath = Paths.get(args[0]);
        // Converts the input Path
        // to an absolute path.
        // Generally, this means prepending
        // the current working
        // directory.  If this example
        // were called like this:
        //     java FileTest foo
        // the getRoot and getParent methods
        // would return null
        // on the original "inputPath"
        // instance.  Invoking getRoot and
        // getParent on the "fullPath"
        // instance returns expected values.
        Path fullPath = inputPath.toAbsolutePath();
    }
}

toAbsolutePath方法转换用户输入并返回一个Path,在查询时返回有用的值。此方法不需要文件存在即可工作。

toRealPath方法返回现有文件的真实路径。该方法一次执行多个操作:

  • 如果向该方法传递true,并且文件系统支持符号链接,则该方法会解析路径中的任何符号链接。
  • 如果Path是相对路径,则返回绝对路径。
  • 如果Path包含任何多余的元素,则返回一个删除了这些元素的路径。

如果文件不存在或无法访问,则此方法会抛出异常。您可以在需要处理这些情况时捕获异常。例如:

try {
    Path fp = path.toRealPath();
} catch (NoSuchFileException x) {
    System.err.format("%s: no such" + " file or directory%n", path);
    // Logic for case when file doesn't exist.
} catch (IOException x) {
    System.err.format("%s%n", x);
    // Logic for other sort of file error.
}

连接两个路径

您可以使用resolve方法组合路径。您传入一个部分路径,即不包括根元素的路径,并将该部分路径附加到原始路径。

例如,考虑以下代码片段:

// Solaris
Path p1 = Paths.get("/home/joe/foo");
// Result is /home/joe/foo/bar
System.out.format("%s%n", p1.resolve("bar"));
or
// Microsoft Windows
Path p1 = Paths.get("C:\\home\\joe\\foo");
// Result is C:\home\joe\foo\bar
System.out.format("%s%n", p1.resolve("bar"));

将绝对路径传递给resolve方法会返回传入的路径:

// Result is /home/joe
Paths.get("foo").resolve("/home/joe");

创建两个路径之间的路径

在编写文件 I/O 代码时,通常需要能够构造从文件系统中的一个位置到另一个位置的路径。您可以使用relativize方法来实现这一点。该方法构造一个源自原始路径并以传入路径指定的位置结束的路径。新路径是相对于原始路径的。

例如,考虑两个定义为joesally的相对路径:

Path p1 = Paths.get("joe");
Path p2 = Paths.get("sally");

在没有其他信息的情况下,假定joesally是兄弟姐妹,即在树结构中处于同一级别的节点。要从joe导航到sally,你需要先向上导航一级到父节点,然后再向下导航到sally

// Result is ../sally
Path p1_to_p2 = p1.relativize(p2);
// Result is ../joe
Path p2_to_p1 = p2.relativize(p1);

考虑一个稍微复杂的例子:

Path p1 = Paths.get("home");
Path p3 = Paths.get("home/sally/bar");
// Result is sally/bar
Path p1_to_p3 = p1.relativize(p3);
// Result is ../..
Path p3_to_p1 = p3.relativize(p1);

在这个例子中,这两个路径共享相同的节点home。要从home导航到bar,你首先向下导航一级到sally,然后再向下导航一级到bar。从barhome的导航需要向上移动两级。

如果只有一个路径包含根元素,则无法构造相对路径。如果两个路径都包含根元素,则构造相对路径的能力取决于系统。

递归Copy示例使用relativizeresolve方法。

比较两个路径

Path类支持equals,使您能够测试两个路径是否相等。startsWithendsWith方法使您能够测试路径是否以特定字符串开头或结尾。这些方法易于使用。例如:

Path path = ...;
Path otherPath = ...;
Path beginning = Paths.get("/home");
Path ending = Paths.get("foo");
if (path.equals(otherPath)) {
    // *equality logic here*
} else if (path.startsWith(beginning)) {
    // *path begins with "/home"*
} else if (path.endsWith(ending)) {
    // *path ends with "foo"*
}

Path类实现了Iterable接口。iterator方法返回一个对象,使你能够遍历路径中的名称元素。返回的第一个元素是在目录树中最接近根的元素。以下代码片段遍历一个路径,打印每个名称元素:

Path path = ...;
for (Path name: path) {
    System.out.println(name);
}

Path类还实现了Comparable接口。你可以使用compareTo比较Path对象,这对于排序很有用。

你也可以将Path对象放入Collection中。查看 Collections trail,了解更多关于这一强大功能的信息。

当你想要验证两个Path对象是否定位到同一文件时,可以使用isSameFile方法,如 Checking Whether Two Paths Locate the Same File 中所述。

文件操作

原文:docs.oracle.com/javase/tutorial/essential/io/fileOps.html

Files类是java.nio.file包的另一个主要入口点。该类提供了丰富的静态方法集,用于读取、写入和操作文件和目录。Files方法适用于Path对象的实例。在继续阅读其余部分之前,您应该熟悉以下常见概念:

  • 释放系统资源
  • 捕获异常
  • 可变参数
  • 原子操作
  • 方法链
  • 什么是 Glob?
  • 链接感知

释放系统资源

此 API 中使用的许多资源,如流或通道,实现或扩展了java.io.Closeable接口。Closeable资源的要求是在不再需要时必须调用close方法来释放资源。忽略关闭资源可能会对应用程序的性能产生负面影响。下一节描述的try-with-resources 语句会为您处理此步骤。


Java 中文官方教程 2022 版(八)(3)https://developer.aliyun.com/article/1486340

相关文章
|
1月前
|
JavaScript NoSQL Java
接替此文【下篇-服务端+后台管理】优雅草蜻蜓z系统JAVA版暗影版为例-【蜻蜓z系列通用】-2025年全新项目整合搭建方式-这是独立吃透代码以后首次改变-独立PC版本vue版搭建教程-优雅草卓伊凡
接替此文【下篇-服务端+后台管理】优雅草蜻蜓z系统JAVA版暗影版为例-【蜻蜓z系列通用】-2025年全新项目整合搭建方式-这是独立吃透代码以后首次改变-独立PC版本vue版搭建教程-优雅草卓伊凡
186 96
接替此文【下篇-服务端+后台管理】优雅草蜻蜓z系统JAVA版暗影版为例-【蜻蜓z系列通用】-2025年全新项目整合搭建方式-这是独立吃透代码以后首次改变-独立PC版本vue版搭建教程-优雅草卓伊凡
|
2月前
|
消息中间件 Java 数据库
自研Java框架 Sunrays-Framework使用教程「博客之星」
### Sunrays-Framework:助力高效开发的Java微服务框架 **Sunrays-Framework** 是一款基于 Spring Boot 构建的高效微服务开发框架,深度融合了 Spring Cloud 生态中的核心技术组件。它旨在简化数据访问、缓存管理、消息队列、文件存储等常见开发任务,帮助开发者快速构建高质量的企业级应用。 #### 核心功能 - **MyBatis-Plus**:简化数据访问层开发,提供强大的 CRUD 操作和分页功能。 - **Redis**:实现高性能缓存和分布式锁,提升系统响应速度。 - **RabbitMQ**:可靠的消息队列支持,适用于异步
自研Java框架 Sunrays-Framework使用教程「博客之星」
|
2月前
|
Java 数据库连接 数据处理
探究Java异常处理【保姆级教程】
Java 异常处理是确保程序稳健运行的关键机制。它通过捕获和处理运行时错误,避免程序崩溃。Java 的异常体系以 `Throwable` 为基础,分为 `Error` 和 `Exception`。前者表示严重错误,后者可细分为受检和非受检异常。常见的异常处理方式包括 `try-catch-finally`、`throws` 和 `throw` 关键字。此外,还可以自定义异常类以满足特定需求。最佳实践包括捕获具体异常、合理使用 `finally` 块和谨慎抛出异常。掌握这些技巧能显著提升程序的健壮性和可靠性。
56 4
|
2月前
|
存储 移动开发 算法
【潜意识Java】Java基础教程:从零开始的学习之旅
本文介绍了 Java 编程语言的基础知识,涵盖从简介、程序结构到面向对象编程的核心概念。首先,Java 是一种高级、跨平台的面向对象语言,支持“一次编写,到处运行”。接着,文章详细讲解了 Java 程序的基本结构,包括包声明、导入语句、类声明和 main 方法。随后,深入探讨了基础语法,如数据类型、变量、控制结构、方法和数组。此外,还介绍了面向对象编程的关键概念,例如类与对象、继承和多态。最后,针对常见的编程错误提供了调试技巧,并总结了学习 Java 的重要性和方法。适合初学者逐步掌握 Java 编程。
58 1
|
3月前
|
移动开发 前端开发 Java
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
JavaFX是Java的下一代图形用户界面工具包。JavaFX是一组图形和媒体API,我们可以用它们来创建和部署富客户端应用程序。 JavaFX允许开发人员快速构建丰富的跨平台应用程序,允许开发人员在单个编程接口中组合图形,动画和UI控件。本文详细介绍了JavaFx的常见用法,相信读完本教程你一定有所收获!
2548 2
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
|
3月前
|
NoSQL Java 关系型数据库
Liunx部署java项目Tomcat、Redis、Mysql教程
本文详细介绍了如何在 Linux 服务器上安装和配置 Tomcat、MySQL 和 Redis,并部署 Java 项目。通过这些步骤,您可以搭建一个高效稳定的 Java 应用运行环境。希望本文能为您在实际操作中提供有价值的参考。
224 26
|
2月前
|
前端开发 Java 开发工具
Git使用教程-将idea本地Java等文件配置到gitte上【保姆级教程】
本内容详细介绍了使用Git进行版本控制的全过程,涵盖从本地仓库创建到远程仓库配置,以及最终推送代码至远程仓库的步骤。
53 0
|
3月前
|
安全 Java 编译器
Kotlin教程笔记(27) -Kotlin 与 Java 共存(二)
Kotlin教程笔记(27) -Kotlin 与 Java 共存(二)
|
3月前
|
Java 开发工具 Android开发
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
|
4月前
|
Java 编译器 Android开发
Kotlin教程笔记(28) -Kotlin 与 Java 混编
Kotlin教程笔记(28) -Kotlin 与 Java 混编
69 2

热门文章

最新文章