RAFs, Random Access Files permit asynchronous (random) access to a file contents. To access a file randomly we open the file, seek a particular position, and then we read or write to that file.

Java NIO.2 introduces a new interface – SeekableByteChannel for working with Random Access Files. Also improves the well-known FileChannel class by implementing this interface.

Before we start to talk about about FileChannel and SeekableByteChannel it is advisable to first talk a little bit about ByteBuffers and Channels.


ByteBuffers

A byte-buffer is an in-memory array of bytes. It usually contains data that was recently read, or that will be written from/to a destination.

A buffer has three important properties:

  • The buffer’s capacity represents the “maximum amount of information” that can be stored in the buffer.
  • The buffer’s position represents how much data has been read or written. The position is an index in the buffer’s array, and cannot have a negative value or a value bigger than the buffer’s capacity.
  • The buffer’s limit is the difference between buffer’s capacity and the buffer’s position.

Channels

Channels are in a way similar with the classical I/O streams, the difference is that while streams are one-way directed (read or write), channels can support both operations in the same time. Also Channels allow you to write and read asynchronously.


Using SeekableByteChannel to write / read to / from files

The SeekableByteChannel interface has 6 methods:

  • position(): Returns the channels current position.
  • position(long): Sets the channel position to the specified value. The value needs to be a positive number.
  • truncate(long): Truncates the entity connected to the SeekableByteChannel to the specified value.
  • read(ByteBuffer): Reads into the buffer (from the channe).
  • write(ByteBuffer): Writes bytes from the buffer to the channel.
  • size(): Returns the current size of the entity to which the channel is connected.

To open a SeekableByteChannel we will need to use the the two methods from the java.nio.file.Files class:

Or:

As you can see to open a seekable channel you need to supply as input the Path you want to open (basically the file) and also open options, which are enum constants.

The possible enum options are as follow:

READ The file is opened with READ access.
WRITE The file is opened with WRITE access.
CREATE Creates the file if the file does not already exist.
CREATE_NEW Creates the file if the file does not already exist. If the file exists throw an exception.
APPPEND Appends to the file. It is used in conjunction with CREATE and WRITE.
DELETE_ON_CLOSE Deletes the file after the channel is closed. Use this when creating and editing / reading from temporary files.
TRUNCATE_EXISTING Truncates the file to size 0. It is used in conjunction with WRITE and it’s useful when you want to clean the contents of a file.
SPARSE Usually used in conjunction with CREATE or CREATE_NEW. On some file systems large files that have big “data gaps” are stored in a more efficient way.
SYNC File content + metadata is synchronized with the underlying file system.
DSYNC File content is synchronized with the underlying file system.

Reading a file using a SeekableByteChannel

Please follow the comments:

Output:


Writing a file using SeekableByteChannel

Please follow the comments:

If we are going to open the file called “file2.txt” from our home folder the content will be:

If we run multiple times the program the content of the file will look like this (the text is appended):


Using the SeekableByteChannel to read characters from different file locations

Given the following acrostic:

We want to read the first 3 letters at the beginning of every word and print on the standard output.

Code example:

And the output of the code:

Introduction

With NIO.2 we can easily determine the attributes of a file by using the java.nio.file.attribute package.

Various file systems have different properties associated with files but NIO.2 groups the attributes into views, each view is specific to a particular file system implementation.

NIO.2 comes with a set of views:

  • BasicFileAttributeView: This view contains a set of common attributes supported by all filesystem implementations. The inner name of the attribute view is ‘basic’.
  • DosFileAttributeView: This view contains a set of attributes specific to filesystems that implement DOS attributes. The inner name of the attribute view is ‘dos’.
  • PosixFileAttributeView: This view contains a set of attributes specific to file systems that support the POSIX standards. The inner name of the attribute view is ‘posix’.
  • AclFileAttributeView: This view is supported by all filesystems implementations that have the concept of ACL. The inner name of the attribute is ‘acl’.
  • FileOwnerAttributeView: This view is supported by all filesystems implementations that have the concept of “ownership” over a file. The inner name of the attribute is ‘owner’.
  • UserDefinedFileAttributeView

How do we determine what are the views supported by our filesystem ?

Output (I am using a Windows 7 machine):

Everytime we want to access the view attributes of a file/folder, it is advisable to check if the file system supports the particular view. NIO.2 allows us to test this using the FileSystem.supportedFileAttributeViews() method .

Eg.:

Output:


Supported file attributes

Every view support file attributes.

BasicFileAttributeView

Attribute Returned Type Comments
“basic:creationTime” FileTime The exact time when the file was created.
“basic:fileKey” Object An object that uniquely identifies a file or null if a file key is not available.
“basic:isDirectory” Boolean Returns true if the file is a directory.
“basic:isRegularFile” Boolean Returns true if a file is not a directory.
“basic:isSymbolicLink” Boolean Returns true if the file is considered to be a symbolic link.
“basic:isOther” Boolean
“basic:lastAccessTime” FileTime The last time when the file was accesed.
“basic:lastModifiedTime” FileTime The time when the file was last modified.
“basic:size” Long The file size.

DosFileAttributeView

Attribute Returned Type Comments
“dos:archive” Boolean Return true if a file is archive or not.
“dos:hidden” Boolean Returns true if the file/folder is hidden.
“dos:readonly” Boolean Returns true if the file/folder is read-only.
“dos:system” Boolean Returns true if the file/folder is system file.

PosixFileAttributeView

Attribute Returned Type Comments
“posix:permissions” Set<PosixFilePermission> The file permissions.
“posix:group” GroupPrincipal Used to determine access rights to objects in a file system

AclFileAttributeView

Attribute Returned Type
“acl:acl” List<AclEntry>
“acl:owner” UserPrincipal

Retrieving file/folder attributes

There are two ways to extract those attributes:

  • Getting a bulk of attributes using readAttributes() method ;
  • Getting single attributes using getAttribute() method .

Retrieving bulk attributes:

Output:

We can also retrieve single attributes. Example:


Updating file/folder attributes

The simplest way to update file attributes is by using the Files.setAttribute method.
In the following example we are going to modify the creation time of a given file:

Output:


Getting attributes of FileStores

To determine the default FileStore object we can invoke FileSystems.getDefault(), but it’s also possible to obtain the list of FileStores by iterating over the list we obtain calling FileSystem.getFileStores() .

Each file store object has dedicated methods for obtaining the name, type, totalSpace etc.

Output:

The Path class is considered to be the entry point for exploring the NIO.2 API. Basically every I/O operation in NIO.2 will exploit the facilities offered by this class.

Path is basically an upgraded version of the java.io.File class.

1. Getting the Path of the Home Directory When you want to obtain the path that points to a specific file in the Home directory, you can proceed as shown. The returned home directory is dependent on each operating system:


2. Obtaining information about the Path: Path Root and Path Parent 


3. Splitting a path in its name elements This is a nice feature that allows the programmer to split the path in it’s forming elements. For example if a file has the following path: ‘C:\Users\andreinc\Downloads\file1.txt’ the following function will retrieve the forming elements of the path, a List containing the following elements: [‘C:\’, ‘Users’, ‘andreinc’, ‘Downloads’, ‘file1.txt’] .

And the output is:


4. Getting the subpath We can extract a relative path using a subpath method. This method accept two parameters, the start (index) and end (index) in the subsequence of elements.

And the output is:


5. Combining two paths
This allows you to define a fixed root path and append to it partial paths.

Output:


6. Comparing two paths
Two paths can be compared as objects, using the “equals()” function. This method is related to the “equals()” method of class Object, thus the compared paths are not required to exist, and this method does not check if the paths are the same file.

But sometimes we want to check if two Path objects represent the same file / folder . In this case we will need to use java.nio.File.Files.isSameFile() method.

Eg.:

Output:

The Path class implements the Comparable interface, thus we can compare two paths by using the compareTo() method . The comparation will be lexicographical, so this will be useful for “sorting”.


7. Iterating over the elements of a Path

The Path class implements the Iterable interface, so we can use a foreach to iterate over the elements of a Path.

Eg.:

Output: