当前位置: 首页 > 编程日记 > 正文

讨论JDK的File.equal()

我们一般比较两个文件中的对象是相同的文件,通常使用java.io.File.equal()。这里,equal()是不是文件内容的比较结果为。象是否指向同一个文件

File的equal()方法。实际上调用了当前文件系统FileSystem的compareTo()。

    public boolean equals(Object obj) {if ((obj != null) && (obj instanceof File)) {return compareTo((File)obj) == 0;}return false;}static private FileSystem fs = FileSystem.getFileSystem();public int compareTo(File pathname) {return fs.compare(this, pathname);}


我们发现,java.io.FileSystem中没有对Unix/Linux的实现,仅仅有Win32FileSystem,所以都是默认调用的这个实现类。 它对文件的比較,事实上就是对文件名称和绝对路径的比較。

假设两个File对象有同样的getPath(),就觉得他们是同一个文件。并且能看出来,Windows是不区分大写和小写的。

如以下的java.io.Win32FileSystem.compare()。

    public int compare(File f1, File f2) {return f1.getPath().compareToIgnoreCase(f2.getPath());}


这样通过比較绝对路径来检验两个对象是否指向同一个文件的方法,能适用大部分的情况,但也要小心。比方说,Linux以下,文件名称对大写和小写是敏感的,就不能ignore了。并且通过硬链接建立的文件,实质还是指向同一个文件的,可是在File.equal()中却为false

所以在JDK1.7后引入了工具类java.nio.file.Files,能够通过isSameFile()来推断两个文件对象是否指向同一个文件。

    public boolean isSameFile(Path path, Path path2) throws IOException {return provider(path).isSameFile(path, path2); }private static FileSystemProvider provider(Path path) {return path.getFileSystem().provider();}

他是获取当前系统的provider,再调用其isSameFile()来校验的。以下的FileSystem的实现层次结构:

        java.nio.file.spi.FileSystemProvider

            sun.nio.fs.AbstractFileSystemProvider

sun.nio.fs.UnixFileSystemProvider

                    sun.nio.fs.LinuxFileSystemProvider

sun.nio.fs.WindowsFileSystemProvider

我们先看看UnixFileSystemProvider.isSameFile() 是怎么实现的:

    public boolean isSameFile(Path obj1, Path obj2) throws IOException {UnixPath file1 = UnixPath.toUnixPath(obj1);if (file1.equals(obj2))return true;file1.checkRead();file2.checkRead();UnixFileAttributes attrs1 = UnixFileAttributes.get(file1, true);UnixFileAttributes attrs2 = UnixFileAttributes.get(file2, true);return attrs1.isSameFile(attrs2);}


他先调用了UnixPath.equal(),然后检查两个文件的可读性,最后再调用了UnixFileAttributes.isSameFile()。

非常显然,他会先检查两个文件的绝对路径是否同样(大写和小写敏感),假设同样的话,就觉得两者是同一个文件。假设不同,再检查两个文件的iNode号。

这是Unix文件系统的特点,文件是通过iNode来标识的,仅仅要iNode号同样,就说明指向同一个文件。

所以能用在推断两个硬链接是否指向同一个文件。

------------------------UnixPath------------------------

    public boolean equals(Object ob) {if ((ob != null) && (ob instanceof UnixPath))return compareTo((Path)ob) == 0;    // compare two pathreturn false;}public int compareTo(Path other) {int len1 = path.length;int len2 = ((UnixPath) other).path.length;int n = Math.min(len1, len2);byte v1[] = path;byte v2[] = ((UnixPath) other).path;int k = 0;while (k < n) {int c1 = v1[k] & 0xff;int c2 = v2[k] & 0xff;if (c1 != c2)return c1 - c2;}return len1 - len2;}

------------------------UnixFileAttributes------------------------

    boolean isSameFile(UnixFileAttributes attrs) {return ((st_ino == attrs.st_ino) && (st_dev == attrs.st_dev));}


而对于Windows系统。也是大同小异,来看看WindowsFileSystemProvider.isSameFile(),WindowsPath.equal()和 WindowsFileAttributes.isSameFile()。

都是先推断文件绝对路径(忽略大写和小写),假设相等就觉得是同一个文件;假设不等就再进行底层推断。Windows底层文件的推断是检查磁盘号是否相等来完毕的。

------------------------ WindowsFileSystemProvider------------------------

    public boolean isSameFile(Path obj1, Path obj2) throws IOException {WindowsPath file1 = WindowsPath.toWindowsPath(obj1);if (file1.equals(obj2))return true;file1.checkRead();file2.checkRead();WindowsFileAttributes attrs1 =WindowsFileAttributes.readAttributes(h1); WindowsFileAttributes attrs2 =WindowsFileAttributes.readAttributes(h2);return WindowsFileAttributes.isSameFile(attrs1, attrs2);}

------------------------ WindowsPath ------------------------  

    public boolean equals(Object obj) {if ((obj != null) && (obj instanceof WindowsPath))return compareTo((Path)obj) == 0;return false;}public int compareTo(Path obj) {if (obj == null)throw new NullPointerException();String s1 = path;String s2 = ((WindowsPath)obj).path;int n1 = s1.length();int n2 = s2.length();int min = Math.min(n1, n2);for (int i = 0; i < min; i++) {char c1 = s1.charAt(i);char c2 = s2.charAt(i);if (c1 != c2) {c1 = Character.toUpperCase(c1);c2 = Character.toUpperCase(c2);if (c1 != c2)return c1 - c2;}}return n1 - n2;}

------------------------ WindowsFileAttributes------------------------

    static boolean isSameFile(WindowsFileAttributes attrs1, WindowsFileAttributes attrs2) {// volume serial number and file index must be the samereturn (attrs1.volSerialNumber == attrs2.volSerialNumber) &&(attrs1.fileIndexHigh == attrs2.fileIndexHigh) &&(attrs1.fileIndexLow == attrs2.fileIndexLow);}

    

这样一比較就清晰了。假设仅仅是对照文件的绝对路径是否相等(不是内容)。能够放心使用File.equal()。而假设要比較在OS中是否指向同一个文件。能够使用Files.isSameFile()。它考虑到了不同文件系统的差异。同一时候。我们通过观察这两种系统校验规则的不同实现,也能窥视到不同OS文件系统的差异。假设你有兴趣,能够进一步深入研究哦!

最后,付上一个OpenJava的源代码地址,你能够在里面找到JDK引用的非常多sun.xxx.xxx的源代码。比如上面提到的一系列sun.nio.fs.xxx。http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7-b147/sun/awt/shell/ShellFolder.java#ShellFolder.compareTo%28java.io.File%29

相关文章:

百度云满速下载(转)

BaiduPCS-GO下载完毕后可以存放到任何位置&#xff0c;建议存放到无中文目录内。然后打开我的电脑→属性→高级系统设置→环境变量→系统变量→Path→编辑→新建&#xff0c;输入你的BaiduPCS-Go存放目录。注意&#xff1a;是存放目录。 这样CMD才可以正确识别到程序。做好所有…

内容协商 (Content Negotiation)

大多数响应包含一个实体&#xff0c;此实体包含人类用户能理解的信息。通常&#xff0c;希望提供给用户相应于请求最容易得到的实体。对服务器和缓存来说&#xff0c;不幸的是&#xff0c;并不是所有的用户都对这个最容易得到的实体有喜好&#xff0c;并且并不是所有的用户代理…

[经验]无线鼠标和无线键盘真的不能用了?——雷柏的重生之路~

逆天大二的时候托朋友买了个雷柏的无线键盘鼠标&#xff1a; 用了很多年&#xff0c;不仅外观好而且键盘鼠标本身也很好用&#xff0c;可前些日子就光荣牺牲了。。。。 逆天百思不得其"姐"&#xff0c;试着把电池换了&#xff0c;发现还是不行&#xff0c;&#xff0…

数字化探索:建立学习型组织,HR 也能驱动业务营收?

本篇文章暨 CSDN《中国 101 计划》系列数字化转型场景之一。 《中国 101 计划——探索企业数字化发展新生态》为 CSDN 联合《新程序员》、GitCode.net 开源代码仓共同策划推出的系列活动&#xff0c;寻访一百零一个数字化转型场景&#xff0c;聚合呈现并开通评选通道&#xff0…

26期20180716 iptables规则备份恢复 firewalld zone

7月16日任务10.19 iptables规则备份和恢复10.20 firewalld的9个zone10.21 firewalld关于zone的操作10.22 firewalld关于service的操作iptables的规则备份和恢复service iptables save会把配置保存到配置文件中 /etc/sysconfig/iptables如果不想保存在这 可以使用iptables-save …

一口气用 Python 写了13个小游戏,摸鱼达人!

来源 | Python小二1、吃金币源码分享&#xff1a;import os import cfg import sys import pygame import random from modules import *游戏初始化 def initGame():# 初始化pygame, 设置展示窗口pygame.init()screen pygame.display.set_mode(cfg.SCREENSIZE)pygame.display.…

关于URL编码

参考&#xff1a;前端工程师的编码遭遇战http://ued.taobao.com/blog/2011/08/26/encode-war/細 談 URL 編碼关于URL编码作者&#xff1a; 阮一峰日期&#xff1a; 2010年2月11日一、问题的由来URL就是网址&#xff0c;只要上网&#xff0c;就一定会用到。一般来说&#xff0c;…

【设计模式】享元模式

上周代码评审&#xff0c;看到同事使用了“享元模式”。想起自己也不懂&#xff0c;着手学习之。 参考的优秀的文章&#xff1a; Java的享元模式 这篇博文为学习之理解、感悟&#xff0c;如理解不真确&#xff0c;请慷慨指出。 本文只讨论单纯享元模式。 Flyweight&#xff0c;…

用D3.js 十分钟实现字符跳动效果

用D3.js 十分钟实现字符跳动效果 注 本文基于 D3.js 作者 Mike Bostock 的 例子原文分为三部分, 在这里笔者将其整合为了一篇方便阅读. 该效果基于 D3.js, 主要使用到了 d3-selection. 如果对d3-selection的基本使用逻辑不太清楚可以参见 这篇文章. 效果图 Step1 首先代码会随机…

HTTP中的缓存

HTTP典型应用于能通过采用缓存技术而提高性能的分布式信息系统。HTTP/1.1协议包括的许多使缓存尽可能的工作的元素。因为这些元素与协议的其他方面有着千丝万缕的联系&#xff0c;而且他们相互作用、影响&#xff0c;因此有必要单独的来介绍基本的缓存设计。如果缓存不能改善性…

Pandas 多层级索引的数据分析案例,超干货!

作者 | 俊欣来源 | 关于数据分析与可视化今天我们来聊一下Pandas当中的数据集中带有多重索引的数据分析实战通常我们接触比较多的是单层索引&#xff08;左图&#xff09;&#xff0c;而多级索引也就意味着数据集当中的行索引有多个层级&#xff08;右图&#xff09;&#xff0…

Angular - - $sce 和 $sceDelegate

$sce $sce 服务是AngularJs提供的一种严格上下文转义服务。 严格的上下文转义服务 严格的上下文转义(SCE)是一种需要在一定的语境中导致AngularJS绑定值被标记为安全使用语境的模式。由用户通过ng-bind-html绑定任意HTML语句就是这方面的一个例子。我们称这些上下文转义为特权或…

Varnish 和 Squid比较到底强多少

对于坊间流传的:1.varnish的性能比squid高10~20倍2.squid 3.0的性能比2.6有提高本次测试将会揭示结果,是否varnish的架构真的能提升那么多的性能是否squid的新版本在性能上有所提升测试中将不对平台.软件.等等进行优化由于优化水平的关系将极大的影响结果.此次测试中的数据可以…

太强了,Python 开发桌面小工具,让代码替我们干重复的工作~

作者 | Cherish 来源 | 杰哥的IT之旅 决定写这篇文章的初衷是来源于一位小伙伴的问题&#xff0c;关于"如何根据数据源用 Python 自动生成透视表"&#xff0c;这个问题背后有个非常好的解决思路&#xff0c;让代码替我们做重复的工作&#xff0c;从而减轻工作量&…

Windows 2008

Windows2008系统实现多用户登录 https://help.aliyun.com/knowledge_detail/6530052.html?spm5176.7618386.5.1.RTfIVT#Windows2008系统实现多用户登录 ECS Windows2008如何支持用户多会话登入 https://help.aliyun.com/knowledge_detail/6511066.html?spm5176.7618386.5.1.f…

java 复制对象有哪些方式

2019独角兽企业重金招聘Python工程师标准>>> java 复制对象有哪些方式 Apache的 Common beanutils库 org.apache.commons.beanutils.BeanUtils.copyProperties(dest,origin);Springframework 的BeanUtil 依赖: <dependency><groupId>org.springframewor…

mysql常用语句集锦

mysql UNIX时间戳与日期的相互转换 UNIX时间戳转换为日期用函数&#xff1a; FROM_UNIXTIME() select FROM_UNIXTIME(1156219870); 日期转换为UNIX时间戳用函数&#xff1a; UNIX_TIMESTAMP() Select UNIX_TIMESTAMP(’2006-11-04 12:23:00′); 例&#xff1a;mysql查询当天的记…

iOS15.4 来袭:新增“男妈妈”表情及口罩面容解锁、AirTags 反跟踪等新功能

整理 | 章雨铭 责编 | 屠敏出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;今日&#xff0c;苹果发布了iOS/iPadOS 15.4正式版。该版本带来了一些重大新功能的更新&#xff0c;包括在戴口罩时使用Face ID功能&#xff0c;以及一些新的表情符号和Siri语音更新…

symfony2项目访问app_dev.php不显示debug工具栏的问题

2019独角兽企业重金招聘Python工程师标准>>> 当在symfony2中比如添加一个bundle后&#xff0c;访问app_dev.php时不会显示底部debug工具栏&#xff0c;一种情况是模板中没有包含有效的html标签 参考&#xff1a;http://stackoverflow.com/questions/10399089/symfon…

PHP的Smarty

原理&#xff1a;把模板文件编译成php文件&#xff0c;然后每次都去读取下模板的修改时间&#xff0c;没有修改就不编译。然后include这个“编译”后的PHP文件。所谓编译也就是模板用正则替换成含PHP代码的过程。实际上并不会每次请求都编译&#xff0c;所以性能尚可。而SMARTY…

真香!精心整理了 100+Python 字符串常用操作

来源丨萝卜大杂烩作者丨周萝卜字符串作为平时使用最多的数据类型&#xff0c;其常用的操作我们还是很有必要熟记于心的&#xff0c;本文整理了多种字符串的操作的案例&#xff0c;还是非常用心&#xff0c;记得点赞收藏~字符串切片操作test "Python Programming" pr…

IOS版添加phonegap-视频播放插件教程

2019独角兽企业重金招聘Python工程师标准>>> 插件集成过程&#xff1a;1.配置Target链接参数选择 Build Settings | Linking | Other Linker Flags, 将该选项的 Debug/Release 键都配置为-ObjC。2.Vitamio SDK 依赖的系统框架和系统库如下:– AVFoundation.framwork…

C#线程同步的几种方法

在网上也看过一些关于线程同步的文章&#xff0c;其实线程同步有好几种方法&#xff0c;下面我就简单的做一下归纳。 一、volatile关键字 volatile是最简单的一种同步方法&#xff0c;当然简单是要付出代价的。它只能在变量一级做同步&#xff0c;volatile的含义就是告诉处理器…

ecshop模板的原理分析

模板的原理 类似Smarty/ECShop这类模板的原理如下图所示。1.首先是编译模板ECShop/Smart是利用PHP引擎&#xff0c;所以编译的结果是一个PHP文件&#xff0c;其编译过程就是将分隔符{}替换成PHP的标准分隔符<?PHP ?>&#xff0c;将$var替换成 echo $var; 或者print $va…

Python 快速生成 web 动态展示机器学习项目!

来源丨网络作者丨wedo实验君1. Streamlit一句话&#xff0c;Streamlit是一个可以用python编写web app的库&#xff0c;可以方便的动态展示你的机器学习的项目。优点你不需要懂html&#xff0c; css&#xff0c; js等&#xff0c;纯python语言编写web app包括web常用组件&#x…

Linux-CentOS 7 增加root分区容量

今天搭建了一台CentOS 7 的机器&#xff0c;搭建完成后通过【df -lh】看了一下分区大小&#xff0c;root分区太小了。 分区.png打算把home分区的容量分一部分给root&#xff0c;具体操作步骤如下&#xff1a; 备份home分区cp -r /home/ homebak卸载【home】目录umount /home/现…

PHP数组实际占用内存大小的分析

http://blog.csdn.net/hguisu/article/details/7376705我们在前面的php高效写法提到&#xff0c;尽量不要复制变量&#xff0c;特别是数组。一般来说&#xff0c;PHP数组的内存利用率只有 1/10, 也就是说&#xff0c;一个在C语言里面100M 内存的数组&#xff0c;在PHP里面就要1…

肝货,详解 tkinter 图形化界面制作流程!

作者 | 黄伟呢来源 | 数据分析与统计学之美本期案例是带着大家制作一个属于自己的GUI图形化界面—>用于设计签名的哦(效果如下图)&#xff0c;是不是感觉很好玩&#xff0c;是不是很想学习呢&#xff1f;限于篇幅&#xff0c;今天我们首先详细讲述一下Tkinter的使用方法。tk…

迁移碰到数据库 Unknown collation: 'utf8mb4_unicode_ci'

数据库从香港服务器迁移到阿里云的虚拟主机&#xff0c;不得不吐槽一下。阿里云的ftp好慢&#xff0c;db导入面板也不够友好。 还得靠中断命令行链接&#xff0c;结果版本太低不支持 utf8mb4_unicode_ci&#xff0c;尼玛&#xff0c;现在都mysql5.7了&#xff0c;您还在 5.1时代…

15-shell 输入/输出重定向

大多数 UNIX 系统命令从你的终端接受输入并将所产生的输出发送回到您的终端。一个命令通常从一个叫标准输入的地方读取输入&#xff0c;默认情况下&#xff0c;这恰好是你的终端。同样&#xff0c;一个命令通常将其输出写入到标准输出&#xff0c;默认情况下&#xff0c;这也是…