6.3.  Read and change file and directory attributes

[Note]

Java 7 NIO.2 API offers access many file attributes. In previous Java releases, you can get only a basic set of file attributes (size, modification time, whether the file is hidden, and whether it is a file or directory). To get or modify any further file attributes, you must implement this yourself in native code specific to the platforms you want to run on. Java 7 allows you to read and, where possible, modify an extended set of attributes in a simple way via the java.nio.file.attribute classes, completely abstracting away the platform-specific nature of these operations.

The following attribute views are available in the new Java 7 NIO.2 API, some of which are specific to the operating system. These "view" classes allow you to get and set whichever attributes they are associated with, and each one has a counterpart attribute class that contains the actual attribute information.

  1. AclFileAttributeView and AclEntry - Supports reading or updating a file's Access Control Lists (ACL). The NFSv4 ACL model is supported. Any ACL model, such as the Windows ACL model, that has a well-defined mapping to the NFSv4 model might also be supported.

    The AclFileAttributeView allows you to get and set the ACL and file-owner attributes of a particular file. Its getAcl() method returns a List of AclEntry objects, one for each permission set on the file. Its setAcl(List<AclEntry>) method allows you to modify that access list. This attribute view is only available for Microsoft Windows systems.

  2. BasicFileAttributeView and BasicFileAttributes - Provides a view of basic attributes that are required to be supported by all file system implementations.

    This view class allows you to get a set of basic file attributes, building on those available in previous Java versions. Its readAttributes() method returns a BasicFileAttributes instance containing details of last modified time, last access time, creation time, size, and type of file (regular file, directory, symbolic link, or other). This attribute view is available on all platforms.

    To get a file attribute view for a particular file we start by creating a Path object for the file we're interested in:

    Path file = Paths.get("C:\\home\\zaikin\\foo\\test.txt");
     								

    To get the file attribute view we want, we will use the getFileAttributeView(Path file, Class viewClass) method on Files. To get the BasicFileAttributeView for file, we simply call:

    BasicFileAttributeView basicView = Files.getFileAttributeView(file, BasicFileAttributeView.class);
     								

    As described earlier, to get the BasicFileAttributes from BasicFileAttributeView, we just call its readAttributes() method:

    BasicFileAttributes basicAttrs = basicView.readAttributes();
     								

    Now you have all of the basic file attributes for that file to do whatever you wish with. For the BasicFileAttributes, only the creation, last-modified, and last-access times can be altered (because it would not make sense to change the size or type of file). To change these, we can use the java.nio.file.attribute.FileTime class to create a new time and then call the setTimes() method on BasicFileAttributeView. For example, we could move the last-modified time for our file a minute further into the future:

    FileTime newTime = FileTime.fromMillis(basicAttrs.lastModifiedTime().toMillis() + 60000);
    basicView.setTimes(newTime, null, null);
    								

    The two nulls indicate that we do not want to change the last access time or creation time for this file. If you check the basic attributes again, in the same way we did earlier, you should see that the last modified time has been altered but the creation time and last access time have remained the same.

  3. DosFileAttributeView and DosFileAttributes - Extends the basic attribute view with the standard four bits supported on file systems that support the DOS attributes.

    This view class allows you to get attributes specific to DOS. This view is for Windows systems only. Its readAttributes() method returns a DosFileAttributes instance containing details of whether the file in question is read-only, hidden, a system file, and an archive. The view also has setXXX(boolean) methods for each of these properties.

    However, you can set a DOS attribute using the Files.setAttribute(Path, String, Object, LinkOption...) method, as follows:

    Path file = ...;
    Files.setAttribute(file, "dos:hidden", true);
    								

  4. FileOwnerAttributeView and UserPrincipal - Supported by any file system implementation that supports the concept of a file owner.

    This view class allows you to get and set the owner of a particular file. Its getOwner() method returns a java.nio.file.attribute.UserPrincipal, which in turn has a getName() method returning a String containing the owner's name. The view also provides a setOwner(UserPrincipal) method allowing you to change a file's owner. This view is available on all platforms.

  5. FileStoreSpaceAttributeView and FileStoreSpaceAttributes

    This view allows you to get information about a particular file store. Its readAttributes() method returns a FileStoreSpaceAttributes instance containing details of the total space, the unallocated space, and the usable space on the file store. This view is available on all platforms.

  6. PosixFileAttributeView and PosixFileAttributes - Extends the basic attribute view with attributes supported on file systems that support the POSIX family of standards, such as UNIX. These attributes include file owner, group owner, and the nine related access permissions.

    This view class, available on UNIX systems only, allows you to get and set attributes specific to POSIX (Portable Operating System Interface). Its readAttributes() method returns a PosixFileAttributes instance containing details of the owner, group owner, and file permissions for this file (those you would normally set using the UNIX chmod command). The view also provides setOwner(UserPrincipal), setGroup(GroupPrincipal), and setPermissions(Set<PosixFilePermission>) methods to modify these attributes.

  7. UserDefinedFileAttributeView and String - Enables support of metadata that is user defined. This view can be mapped to any extension mechanisms that a system supports. In the Solaris OS, for example, you can use this view to store the MIME type of a file.

    This view class, available only on Windows, allows you to get and set extended attributes on files. These attributes are unlike the others in that they are just name-value pairs and can be set to anything you wish. This can be useful if you want to add some hidden metadata to a file without altering the file's content. The view provides a list() method that returns a List of String names of the extended attributes for the relevant file.

    To get the contents of a particular attribute once you have its name, the view has a size(String name) method to return the size of the attribute's value and a read(String name, ByteBuffer dest) method to read the attribute value into the ByteBuffer. The view also provides a write(String name, ByteBuffer source) method to create or alter an attribute, and also a delete(String name) method to remove an existing attribute entirely.

    This is probably the most interesting new attribute view because it allows you to add attributes with arbitrary String names and ByteBuffer values to files, so you can store any binary data in there you want.

    First, we will get the attribute view:

    Path file = Paths.get("C:\\home\\zaikin\\foo\\test.txt");
    UserDefinedFileAttributeView userView = Files.getFileAttributeView(file, UserDefinedFileAttributeView.class);
    								

    To set your own attribute, you simply need to create your ByteBuffer and fill it with whatever data you wish and then call the write(String, ByteBuffer) method on the view:

    String attribName  = "COPYRIGHT";
    String attribValue = "MIKALAI.ZAIKIN";
    userView.write(attribName, Charset.defaultCharset().encode(attribValue));
    								

    Writing an attribute either creates that attribute or overwrites an existing attribute with the same name.

    To get a list of the user-defined attribute names for this file, we call the list() method on the view:

    
    List<String> attribList = userView.list();
    
    								

    Once we have a particular attribute name we wish to get the associated value for, we allocate a ByteBuffer of the right size for the value and then call the view's read(String, ByteBuffer) method:

    for (String s : attribList) {
        System.out.print(String.format("User defined attribute: %s", s));
        ByteBuffer buf = ByteBuffer.allocate(userView.size(s));
        userView.read(s, buf);
        buf.flip();
        String value = Charset.defaultCharset().decode(buf).toString();
        System.out.println(String.format("; value: %s", value));
    }
    								

    The output will be as follows:

    User defined attribute: COPYRIGHT; value: MIKALAI.ZAIKIN
    								

File store attributes

You can use the FileStore class to learn information about a file store, such as how much space is available. The getFileStore(Path) method fetches the file store for the specified file.

The following code snippet prints the space usage for the file store where a particular file resides:

Path file = ...;
FileStore store = Files.getFileStore(file);

long total = store.getTotalSpace()  / 1024 / 1024;
long avail = store.getUsableSpace() / 1024 / 1024;
long used = (store.getTotalSpace() - store.getUnallocatedSpace()) / 1024 / 1024;

System.out.print(String.format("Root : %s%n", file.getRoot()));
System.out.print(String.format("Store name: %s%n", store.name()));
System.out.print(String.format("Total: %d MB; used: %d MB; available: %d MB", total, used, avail));
					

Professional hosting         Free 'Oracle Certified Expert Web Services Developer 6' Guide     Free SCDJWS 5.0 Guide