Monday, 26 February 2018

Dealing with Files and Directories in Java - 10 Thing Java Developer Should Know

The File API is one of the important parts of any programming language or API and even though Java's file API both new and old, are powerful, they are not intuitive enough compared to other languages e.g. Python. Apart from knowing the essential classes and abstractions e.g. File, InputStream, OutputStream, Reader, Writer, Channel etc, you also need to know and remember some nitty gritty detail to avoid subtle issues. There are many articles out there on the internet which can teach you how to read and write data from the file but there are very few which will tell you to do it in right way.

There are things you only learn when you do meaningful work e.g. reading/writing data from a real file and in a real production environment where things like missing data and corrupted data and performance matter. If you have good understanding of basics of File API in Java then only you can write code which can stand test of time.

Unfortunately, there is no serious book which will teach you the effective way of file handling in Java, at least I don't know, if you know please share. Even Effective Java 3rd Edition doesn't cover File handling API, despite covering most of the stuff.

To start with, I am going to share some of the basic stuff related to file handling in Java, which goes a long way to find and troubleshoot any file related issues in production.

If you have been working in Java for a couple of years and exposed to the file API then you might already know most of the points and possibly you can add a few more into the list and I encourage you to do so and share your experience with us. There is no better way of learning than sharing knowledge.

Anyway, without further ado, here are some of the basics about file and directory handling in Java.

10 things  to remember while reading, writing from/to a file in Java

Here is my list of 10 essential things Java developer should know about File handling in Java programming language.  These are mainly basic stuff but I was surprised when many programmers never heard about it. You might know some of these already but if you learn something new then don't forget to say thanks.

1) The same class is used to represent both file and directory in Java. You can use the isDirectory() and isFile() method from the class to check if you are actually working with a file or directory.  See this article to learn more about File and Directory in Java.

2) In Java, InputStream is used for reading data and OutputStream is used for writing data. In the context of a file, FileInputStream is used to read data from a file and FileOutputStream is used to write data into the file. I know, it's easy to remember that one you know but I have seen many Java programmers struggling with InputStream and OuputStream and their meaning.

3) Java provides different classes for different needs in package, for example, Stream classes e.g. InputStream and OutputStream are used to read and write binary data while Reader and Writer e.g. BufferedReader and BufferedWriter are used to writing character or text data.

4) It is very important to close the stream after using it, as it is not closed implicitly, to release any resources associated with it, while in the output stream, the close() method calls flush() before releasing the resources which force any buffered bytes to be written to the stream. See Complete Java 9 Masterclass to learn more about how to close Stream in right way.

Oracle Java Tutorials and Materials, Oracle Java Guides, Oracle Java Certifications, Oracle Java Learning

5) If we try to read from a file that doesn’t exist, a FileNotFoundException will be thrown but If we try to write to a file that doesn’t exist, the file will be created first and no exception will be thrown

6) FileReader and FileWriter classes are used to read/write data from a text file in Java. Even though you can use FileInputStream and FileOutputStream, FileReader and FileWriter are more efficient and handles character encoding issues for you. 

7) If you are dealing with a shared file then make sure you lock the file before writing into it. You can use the FileLock interface for locking the portion of the file. You can get the associated lock for a file by calling the FileChannel.getLock() method. 

8) Make sure you know the right way to close the stream in Java because calling the close itself can throw IOException. See my post about how to properly close input and output stream in Java to learn more.

9) The and java.nio package provides several classes to write different kinds of data on the different situation.  For example, you can use

◈ PrintWriter to write formatted text;
◈ FileOutputStream to write binary data; 
◈ FileWrite to writer text data, 
◈ DataOutputStream to write primitive data types; 
◈ RandomAccessFile to write to a specific position, and 
◈ FileChannel to write faster in bigger files.

10) Use the JDK 7 new file API as much as possible, particularly for writing new code. Spend some time know and understand the new File API introduced in JDK 7, at least the java.nio.file.Files class, which allows you to create, read, write, copy, move, and delete files and directories in Java.

That's all about some of the interesting and useful points to remember while dealing with a file in Java. If you know these points then you can effectively read and write data from a file, avoiding common mistakes made by many Java programmers, who don't know the JDK's file API better. To be honest, it's not the most intuitive library and some efforts have been made in JDK 7 by introducing the New File API but still, you can't ignore these points if you are dealing with files in Java.