Introduction
The java.nio.file.Files
class includes many convenient methods to read file attributes, but sometimes these convenient methods just are not enough to meet our needs.
In this tutorial, we will go over 5 ways to use the Files
class to read file attributes so you can choose the best way for your use case.
Goals
At the end of the tutorial, you would have learned:
- 5 different ways to view file attributes with Java NIO.
Prerequisite Knowledge
- Basic Java.
- Java NIO/IO.
Tools Required
- A Java IDE such as IntelliJ Community Edition or Eclipse.
Project Setup
To follow along with the tutorial, perform the steps below:
-
Create a new Java project.
-
Create a package
com.example
. -
Create a class called
Entry
. -
Create the
main()
method insideEntry.java
. -
Copy and paste the following content into the
main()
method.Path path = Path.of(".", "Test.txt"); createTestFile(path); viewAttributes1(path); viewAttributes2(path); viewAttributes3(path); viewAttributes4(path); viewAttributes5(path);
-
Create the creatTestFile() method like below:
private static void createTestFile(Path path){ try { if (Files.notExists(path)) Files.createFile(path); } catch (IOException e) { e.printStackTrace(); } }
-
The code will not compile yet because we are missing those
viewAttributes()
methods, which we will add later.
Read file attributes using convenient methods
As of Java 17, the Files class has 10 convenient methods to read file attributes. They are great to use because they are idiomatic and are very readable.
Files.getLastModifiedTime(path); //1
Files.isDirectory(path); //2
Files.isRegularFile(path); //3
Files.isSymbolicLink(path); //4
Files.isExecutable(path); //5
Files.isHidden(path); //6
Files.isReadable(path); //7
Files.isWritable(path); //8
Files.size(path); //9
Files.getOwner(path); //10
Let us create the first viewAttributes()
method from the code below using the convenient methods from Files
(put all of them inside the Entry
class).
private static void viewAttributes1(Path path) {
try {
Files.getLastModifiedTime(path); //1
Files.isDirectory(path); //2
Files.isRegularFile(path); //3
Files.isSymbolicLink(path); //4
Files.isExecutable(path); //5
Files.isHidden(path); //6
Files.isReadable(path); //7
Files.isWritable(path); //8
Files.size(path); //9
Files.getOwner(path); //10
} catch (IOException e){
System.out.println(e);
}
}
Read file attributes from an AttributesView object
Besides using the convenient methods from Files
, we can also use the AttributeView
implementations. AttributeView
is the top interface in the hierarchy of file attribute views, as depicted in the picture below.
For this tutorial, we are only concerned about the DosFileAttributeView
(or you can substitute for PosixFileAttributeView
if you are using Linux/Mac).
The BasicFileAttributeView
supports file attributes in multiple file systems, so it can be used on any file system, but some attributes are specific to the operating systems, so we need to use the Dos/Posix
attribute views to access those.
To get the FileAttributeView
object, we can use the method Files.getFileAttributeView()
. Its signature is below:
static <V extends FileAttributeView> V getFileAttributeView(Path path, Class<V> type, LinkOption... options)
The only thing that is special about the above method is that we need to pass in the Class
object of the FileAttributeView
that we want (dos or posix). After we get the AttributeView
object that we want, we can call the method readAttributes()
on the AttributeView
implementation and access the supported file attributes.
Create the viewAttributes2()
method like the code below.
private static void viewAttributes2(Path path){
try {
DosFileAttributes attributes = Files
.getFileAttributeView(path, DosFileAttributeView.class)
.readAttributes();
attributes.lastModifiedTime(); //1
attributes.lastAccessTime(); //2
attributes.creationTime(); //3
attributes.isDirectory(); //4
attributes.isRegularFile(); //5
attributes.isSymbolicLink(); //6
attributes.isOther(); //7
attributes.fileKey(); //8
attributes.size(); //9
attributes.isHidden(); //10
attributes.isSystem(); //11
attributes.isArchive(); //12
attributes.isReadOnly(); //13
} catch (IOException e) {
e.printStackTrace();
}
}
As you can see, we now have 13 methods to read file attributes, which are 3 more than the convenient Files
methods(although not all of them overlap).
Read file attributes from a BasicFileAttributes object
Besides the View
object, it is also possible to use the BasicFileAttributes
object itself (with implementation-specific variants as well). To get back a DosFileAttributes
object, use the Files.readAttributes()
object with the signature below.
static <A extends BasicFileAttributes> A readAttributes(Path path, Class<A> type, LinkOption... options)
Because we receive the DosFileAttributes
object directly from this method, we can just access these attributes right away.
Create the viewAttributes3()
method from the code below.
private static void viewAttributes3(Path path){
try {
DosFileAttributes attributes = Files.readAttributes(path, DosFileAttributes.class); //similar to viewAttributes2()
attributes.lastModifiedTime(); //1
attributes.lastAccessTime(); //2
attributes.creationTime(); //3
attributes.isDirectory(); //4
attributes.isRegularFile(); //5
attributes.isSymbolicLink(); //6
attributes.isOther(); //7
attributes.fileKey(); //8
attributes.size(); //9
attributes.isHidden(); //10
attributes.isSystem(); //11
attributes.isArchive(); //12
attributes.isReadOnly(); //13
} catch (IOException e){
e.printStackTrace();
}
}
As you can see, the functionality is technically the same as the previous method. With the View
objects, we are able to modify the file attributes, whereas with just the Attributes
objects, we can only read.
Read individual file attributes
The BasicFileAttributes
and BasicFileAttributeView
objects allow for reading attributes in bulk, but what if we only want to read a specific attribute that is implementation specific? Files.getAttributes()
is what we need to use in this case. Its method signature is:
public static Object getAttribute(Path path, String attribute, LinkOption... options) throws IOException
This time, we are no longer passing in the Class
objects, but a String
in a specific format.
[view-name:]attribute-list
To mirror the functionalities of the DosFileAttributes
object in the previous section, we create the viewAttributes4()
method like below.
public static void viewAttributes4(Path path){
try {
Files.getAttribute(path, "dos:lastModifiedTime"); //1
Files.getAttribute(path, "dos:lastAccessTime"); //2
Files.getAttribute(path, "dos:creationTime"); //3
Files.getAttribute(path, "dos:size"); //4
Files.getAttribute(path, "dos:isRegularFile"); //5
Files.getAttribute(path, "dos:isDirectory"); //6
Files.getAttribute(path, "dos:isSymbolicLink"); //7
Files.getAttribute(path, "dos:isOther"); //8
Files.getAttribute(path, "dos:fileKey"); //9
Files.getAttribute(path, "dos:readonly"); //10
Files.getAttribute(path, "dos:hidden"); //11
Files.getAttribute(path, "dos:system"); //12
Files.getAttribute(path, "dos:archive"); //13
} catch (IOException e){
e.printStackTrace();
}
}
The part of the string before the colon is the view name, which is the same as any of the AttributeView
implementation’s name()
method. The part after the colon is the attribute name.
Read file attributes as a Map
There is another method that allows for reading file attributes directly into a Map
, and its signature is:
public static Map<String,Object> readAttributes(Path path, String attributes, LinkOption... options) throws IOException
Note that this method also takes the String
form like the Files.getAttribute()
method, but if we want to read all of the attributes, we do not have to provide all of the attribute names. Instead, we can just provide a wildcard character to get all of the attributes into a Map
.
Create the viewAttributes5()
method like below.
public static void viewAttributes5(Path path){
try {
Map<String, Object> attrMap = Files.readAttributes(path, "dos:*"); //gets a Map
} catch (IOException e){
e.printStackTrace();
}
}
Solution Code
package com.example;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.*;
import java.util.Map;
public class Entry {
public static void main(String[] args){
Path path = Path.of(".", "Test.txt");
createTestFile(path);
viewAttributes1(path);
viewAttributes2(path);
viewAttributes3(path);
viewAttributes4(path);
viewAttributes5(path);
}
private static void createTestFile(Path path){
try {
if (Files.notExists(path))
Files.createFile(path);
} catch (IOException e) {
e.printStackTrace();
}
}
private static void viewAttributes1(Path path) {
try {
Files.getLastModifiedTime(path); //1
Files.isDirectory(path); //2
Files.isRegularFile(path); //3
Files.isSymbolicLink(path); //4
Files.isExecutable(path); //5
Files.isHidden(path); //6
Files.isReadable(path); //7
Files.isWritable(path); //8
Files.size(path); //9
Files.getOwner(path); //10
} catch (IOException e){
System.out.println(e);
}
}
private static void viewAttributes2(Path path){
try {
DosFileAttributes attributes = Files
.getFileAttributeView(path, DosFileAttributeView.class)
.readAttributes();
attributes.lastModifiedTime(); //1
attributes.lastAccessTime(); //2
attributes.creationTime(); //3
attributes.isDirectory(); //4
attributes.isRegularFile(); //5
attributes.isSymbolicLink(); //6
attributes.isOther(); //7
attributes.fileKey(); //8
attributes.size(); //9
attributes.isHidden(); //10
attributes.isSystem(); //11
attributes.isArchive(); //12
attributes.isReadOnly(); //13
} catch (IOException e) {
e.printStackTrace();
}
}
private static void viewAttributes3(Path path){
try {
DosFileAttributes attributes = Files.readAttributes(path, DosFileAttributes.class); //similar to viewAttributes2()
attributes.lastModifiedTime(); //1
attributes.lastAccessTime(); //2
attributes.creationTime(); //3
attributes.isDirectory(); //4
attributes.isRegularFile(); //5
attributes.isSymbolicLink(); //6
attributes.isOther(); //7
attributes.fileKey(); //8
attributes.size(); //9
attributes.isHidden(); //10
attributes.isSystem(); //11
attributes.isArchive(); //12
attributes.isReadOnly(); //13
} catch (IOException e){
e.printStackTrace();
}
}
public static void viewAttributes4(Path path){
try {
Files.getAttribute(path, "dos:lastModifiedTime"); //1
Files.getAttribute(path, "dos:lastAccessTime"); //2
Files.getAttribute(path, "dos:creationTime"); //3
Files.getAttribute(path, "dos:size"); //4
Files.getAttribute(path, "dos:isRegularFile"); //5
Files.getAttribute(path, "dos:isDirectory"); //6
Files.getAttribute(path, "dos:isSymbolicLink"); //7
Files.getAttribute(path, "dos:isOther"); //8
Files.getAttribute(path, "dos:fileKey"); //9
Files.getAttribute(path, "dos:readonly"); //10
Files.getAttribute(path, "dos:hidden"); //11
Files.getAttribute(path, "dos:system"); //12
Files.getAttribute(path, "dos:archive"); //13
} catch (IOException e){
e.printStackTrace();
}
}
public static void viewAttributes5(Path path){
try {
Map<String, Object> attrMap = Files.readAttributes(path, "dos:*"); //gets a Map
} catch (IOException e){
e.printStackTrace();
}
}
}
Summary
We have learned how to read file attributes in Java NIO using 5 different ways. To provide a rough comparison (only applicable to the Dos variants) between the 5 ways, you can refer to the picture below.
The full project code can be found here: https://github.com/dmitrilc/DaniwebJavaNioFileAttribute