目录
2、setReadOnly / setWritable / setReadable / setExecutable / canExecute / canRead / canWrite
3、getTotalSpace / getFreeSpace / getUsableSpace
4、compareTo / equals / hashCode
本篇博客继续上一篇《Java8 File / FileSystem(一) 源码解析》讲解File其他方法的源码实现。
1、renameTo / setLastModified
public boolean renameTo(File dest) {
SecurityManager security = System.getSecurityManager();
if (security != null) {
//校验访问权限
security.checkWrite(path);
security.checkWrite(dest.path);
}
if (dest == null) {
throw new NullPointerException();
}
//校验路径合法性
if (this.isInvalid() || dest.isInvalid()) {
return false;
}
return fs.rename(this, dest);
}
//UnixFileSystem的实现
public boolean rename(File f1, File f2) {
//清除路径解析的缓存
cache.clear();
javaHomePrefixCache.clear();
//本地方法
return rename0(f1, f2);
}
public boolean setLastModified(long time) {
if (time < 0) throw new IllegalArgumentException("Negative time");
SecurityManager security = System.getSecurityManager();
if (security != null) {
//校验访问权限
security.checkWrite(path);
}
if (isInvalid()) { //校验路径合法性
return false;
}
//本地方法实现
return fs.setLastModifiedTime(this, time);
}
涉及的本地方法实现都在UnixFileSystem_md.c中,其核心是用于文件重命名的rename函数和用于修改文件最后修改时间的utimes函数,如下:
JNIEXPORT jboolean JNICALL
Java_java_io_UnixFileSystem_rename0(JNIEnv *env, jobject this,
jobject from, jobject to)
{
jboolean rv = JNI_FALSE;
WITH_FIELD_PLATFORM_STRING(env, from, ids.path, fromPath) {
WITH_FIELD_PLATFORM_STRING(env, to, ids.path, toPath) {
//调用rename函数,如果toPath在另一个目录下,则相当于移动文件并重命名,如果toPath已存在则rename失败
if (rename(fromPath, toPath) == 0) {
rv = JNI_TRUE;
}
} END_PLATFORM_STRING(env, toPath);
} END_PLATFORM_STRING(env, fromPath);
return rv;
}
JNIEXPORT jboolean JNICALL
Java_java_io_UnixFileSystem_setLastModifiedTime(JNIEnv *env, jobject this,
jobject file, jlong time)
{
jboolean rv = JNI_FALSE;
WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
struct stat64 sb;
//调用stat64函数获取文件属性
if (stat64(path, &sb) == 0) {
struct timeval tv[2];
/* 之前的文件修改时间 */
tv[0].tv_sec = sb.st_atime;
tv[0].tv_usec = 0;
/* 指定的文件修改时间,time是毫秒数 */
tv[1].tv_sec = time / 1000; //转换成秒数
tv[1].tv_usec = (time % 1000) * 1000; //上述秒数对应的毫秒数
//调用utimes函数修改文件属性
if (utimes(path, tv) == 0)
rv = JNI_TRUE; //修改成功,返回true
}
} END_PLATFORM_STRING(env, path);
return rv;
}
测试用例如下:
@Test
public void test6() throws Exception {
File file=new File("D:\\code\\test.txt");
Calendar calendar=Calendar.getInstance();
calendar.add(Calendar.HOUR,-1);
System.out.println("setLastModified:"+file.setLastModified(calendar.getTimeInMillis()));
System.out.println("lastModified:"+file.lastModified());
//如果目标路径对应的文件已存在,则返回false
System.out.println("renameTo:"+file.renameTo(new File("D:\\test2.txt")));
}
2、setReadOnly / setWritable / setReadable / setExecutable / canExecute / canRead / canWrite
这几个都是获取或者修改文件的可读可写可执行权限的,如下:
public boolean canRead() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkRead(path);
}
if (isInvalid()) {
return false;
}
//本地方法实现
return fs.checkAccess(this, FileSystem.ACCESS_READ);
}
public boolean canWrite() {
SecurityManager security = System.getSecurityManager(