1. NIO.2对文件属性访问的全面升级:
1) 旧版本中File类只提供了一些非常简单的文件属性访问功能,基本上只是可以获取文件属性值,但通常不能修改;
2) NIO.2专门在java.nio.file包下增加了一个attribute包(即java.nio.file.attribute),里面提供了大量的文件属性访问及修改API,基本上可以全面使用OS的文件系统功能;
3) 对于文件属性访问功能的设计,细心的Java仍然采用MVC的设计模式进行构架:
i. 它将属性的集合都放在“视图”这种结构中,因为一般文件属性都是由OS自己来管理,用户只不过是在执行某个操作时“不经意地“、”自动地“触发了文件属性修改的动作而已,因此Java就将属性的集合放在”视图“中,这是站在用户角度考虑;
ii. Java按照功能和类别将文件属性分成了好几种,而最顶层的是FileAttributeView,这是个接口,表示所有文件属性视图的父视图,而其低下则派生了很多各种类型的文件属性视图:这里介绍几个最常用的
a. BasicFileAttributeView:基础文件属性,包括文件修改时间、创建时间、最后修改时间、文件大小、是否为目录、是否为快捷方式等,这也是最最常用的;
b. FileOwnerAttributeView:文件主人的相关属性,其只有两个功能,一个是获取当前文件的所属人,另一个是修改当前文件的所属人;
c. DosFileAttributeView:获取和修改文件的Dos属性(Windows中的特性),比如检查文件是否为隐藏、是否是归档文件,其使用程度仅次于BasicFileAttributeView;
d. UserDefinedFileAttributeView:用户自定义文件属性,一般OS在开发层面都允许用户自定义文件的一些属性,自定义属性必然使用键值对来表示,键是属性的名称(需要自定义),而值则是属性的值(属性的值可以是任意类型的,因此需要用二进制字节来保存,读取和保存时需要用到ByteBuffer);
iii. 对于最常用的BasicFileAttributeView和DosFileAttributeView,Java还提供了更深一层的设计,需要通过各自的readAttributes方法分别获得BasicFileAttributes对象和DosFileAttributes对象才能真正访问其中的属性以及修改属性,其它几种不常用的文件属性可以直接通过视图访问和修改属性,但是这两种用的太多,考虑到这些功能可能会运用到大型MVC构架中,因此专门为它们两个设计了工厂方法readAttributes,通过该方法才能真正获得属性的集合BasicFileAttributes和DosFileAttributes;
2. 通过Files的工厂方法获取一个具体的文件属性视图对象:
1) 访问文件属性在NIO.2中必然有两要素,一个是目标文件,另一个是属性的类型;
2) Files的工具方法getFileAttributeView可以解决这两个问题:
i. 原型:static <V extends FileAttributeView> V Files.getFileAttributeView(Path path, Class<V> type, LinkOption... options);
ii. path就是目标文件,type就是属性的类型,options是链接选项,这个暂时不用管,使用时忽略该参数即可;
iii. type直接传某种视图的class成员即可;
iv. 使用方法:XxxXxxAttributeView xxxView = Files.getFileAttributeView(path, XxxXxxAttributeView.class);
v. 例如获取A处理FileAttributeView对象就可以这样:AclFileAttributeView aclView = Files.getFileAttributeView(Paths.get("xxx.txt"), AclFileAttributeView.class);
3) 得到视图后既可以正常的访问或者修改文件属性了;
3. BasicFileAttributeView:只读视图(只能查看的属性,不能修改的属性)
1) 基础文件属性不能直接通过视图来访问,必须要通过视图的readAttributes方法获得对应的BasicFileAttributes属性集合对象,然后用该属性集合对象才能正常访问和修改文件属性:BasicFileAttributes BasicFileAttributeView.readAttributes();
2) BasicFileAttriubtes中共有8大方法获取文件的基础属性信息:3时间-4类型-1大小(都是BasicFileAttributes的对象方法)
i. 查看时间:
a. FileTime lastModifiedTime(); // 最后修改时间
b. FileTime lastAccessTime(); // 最近访问时间
c. FileTime creationTime(); // 创建时间
!!一般会调用FileTime的toMillis得到毫秒时间:long FileTime.toMillis();
ii. 查看文件类型:
a. boolean isRegularFile(); // 是否是正常文件(txt、exe等非目录类型的文件)
b. boolean isDirectory(); // 是否是目录
c. boolean isSymbolicLink(); // 是否为符号链接,即快捷方式
d. boolean isOther(); // 其它类型(特别是Unix中的块设备文件等,但是在Windows中不常见)
iii. 文件大小:long size(); // 文件的字节大小
4. DosFileAttributeView:可查看可修改的视图
1) 查看属性和BasicFileAttributeView一样,必须通过readAttributes获得DosFileAttributes集合,然后调用集合的方法查看属性:
DosFileAttributes DosFileAttributeView.readAttributes();
2) 由于DosFileAttributes直接继承自BasicFileAttributes,因此BasicFileAttributes中的查看功能DosFileAttributes里全都有,这里只介绍DosFileAttributes里独有的查看功能:都是DosFileAttributes的对象方法
i. boolean isReadOnly(); // 是否是只读
ii. boolean isHidden(); // 是否是隐藏文件
iii. boolean isArchive(); // 是否是归档文件(即压缩文件)
iv. boolean isSystem(); // 是否是操作系统组件(Windows操作系统的组件)
!!由于DosFileAttributes是Dos系统特有的,因此如果专门是Windows上的应用可以直接用DosFileAttributeView,但如果是跨平台的或者在其它平台上运行的最好是只用BasicFileAttributeView;
3) 修改Dos文件属性直接使用视图修改:都是DosFileAttributeView的对象方法,和查看是相对应的
i. void setReadOnly(boolean value); // 设置只读
ii. void setHidden(boolean value); // 设置隐藏
iii. void setArchive(boolean value); // 设置归档
5. 自定义属性——UserDefinedFileAttributeView:
1) Java允许用视图UserDefinedFileAttributeView为文件自定义属性;
2) 属性用键值对定义,键即属性的名称,是String类型的,键所对应的值就是属性值,直接用二进制字节码来表示(这样可以表示任意类型的数据);
!!接下来介绍的都是UserDefinedFileAttributeView的对象方法;
3) 添加属性:int write(String name, ByteBuffer src); // 直接向视图中写入一个键值对
4) 读取属性:int read(String name, ByteBuffer dst); // 读取一个键值对
!!上面的返回值都表示写入/读取了多少个字节;
5) 属性值的大小:int size(String name); // 字节
6) 列出所有的自定义属性名:List<String> list();
6. 综合示例:
public class Test {
public static void main(String[] args) throws IOException, InterruptedException {
Path path = Paths.get("out.txt");
BasicFileAttributeView basicFileAttributeView = Files.getFileAttributeView(path, BasicFileAttributeView.class);
BasicFileAttributes basicFileAttributes = basicFileAttributeView.readAttributes();
System.out.println("创建时间 : " + new Date(basicFileAttributes.creationTime().toMillis()));
DosFileAttributeView dosFileAttributeView = Files.getFileAttributeView(path, DosFileAttributeView.class);
dosFileAttributeView.setHidden(true);
// 写入一个属性
UserDefinedFileAttributeView userDefinedFileAttributeView = Files.getFileAttributeView(path, UserDefinedFileAttributeView.class);
userDefinedFileAttributeView.write("版权人", Charset.defaultCharset().encode("啦啦啦"));
List<String> attrNames = userDefinedFileAttributeView.list(); // 读出所有属性
for (String name: attrNames) {
ByteBuffer bb = ByteBuffer.allocate(userDefinedFileAttributeView.size(name)); // 准备一块儿内存块读取
userDefinedFileAttributeView.read(name, bb);
bb.flip();
String value = Charset.defaultCharset().decode(bb).toString();
System.out.println(name + " : " + value);
}
}
}