Monday 10 July 2017

Java Files



Java provides a standard way of reading from and writing to files. Traditionally the java.io package was used, but in modern Java applications you use the java.nio.file API.

Java will read all input as a stream of bytes. The InputStream class is the superclass of all classes representing an input stream of bytes.

The File class in the Java IO API gives you access to the underlying file system. Using the File class you can:
  • Check if a file or directory exists.
  • Create a file or directory if it does not exist.
  • Read the length of a file.
  • Rename or move a file.
  • Delete a file.
  • Check if path is file or directory.
  • Read list of files in a directory.
Instantiating a java.io.File:

Before you can do anything with the file system or File class, you must obtain a File instance. Here is how that is done:

File txtFile= new File("c:\\temp\\text-file.txt");

Let's look at some widely used methods of File class.

createNewFile Method:

This method creates an empty file, if the file doesn’t exist at the specified location and returns true. If the file is already present then this method returns false. It throws:

IOExceptionIf an Input/Output error occurs during file creation.

Usage:

File txtFile= new File("c:\\temp\\text-file.txt");
boolean fvar = file.createNewFile();



exists Method:

To check if the file exists within the file system, use the exists() method. Returns true if exists or false if does not exists.

Usage:

File txtFile= new File("c:\\temp\\text-file.txt");
boolean fileExists = txtFile.exists(); 


mkdir/mkdirs Method:

mkdir() and mkdirs() are used to create directories if they don't already exists.


The mkdir() method creates a single directory if it does not already exist.

Usage:

File file = new File("c:\\temp\\newdir"); 
boolean dirCreated = file.mkdir();

If the directory c:\temp\ already exists, the above code will create a subdirectory of  newdirnamed newdir. The mkdir() returns true if the directory was created, and false if not.

The mkdirs() will create all directories that are missing in the path the File object represents.

Usage:

File file = new File("c:\\temp\\newdir");
boolean dirCreated = file.mkdirs();

Let's assume there is no temp directory in C drive and you are trying to create newdir directory in temp. mkdirs will create all that missing directories, in our case newdir along with missing directory temp.

Now let's put all mobe methods together to create a temp\\newdir directories in C drive if they do not already exist and create a text file in newdir directory if the file already not exists.

import java.io.File;
import java.io.IOException;

public class FilesDemo {

  public static void main(final String[] args) throws IOException {

    // Create File instance with the reference to directory we want
    final File dir = new File("c:\\temp\\newdir");

    // Check if directory already exists
    final boolean isDirExists = dir.exists();

    // If directory not exists
    if (!isDirExists) {
      // Create all directories that are missing
      final boolean dirCreated = dir.mkdirs();
      // Check if directory creation is successful
      if (dirCreated) {
        System.out.println("Directories created successfully");
      }
    }

    // Create File instance with the reference to file we want
    final File txtFile = new File("c:\\temp\\newdir\\text-file.txt");
    // Check if file already exists
    final boolean isFileExists = txtFile.exists();

    // If file not exists
    if (!isFileExists) {
      // Create file
      final boolean fileCreated = txtFile.createNewFile();
      // Check if created
      if (fileCreated) {
        System.out.println("Text file created successfully");
      }
    }
  }
}

Output:
Directories created successfully
Text file created successfully


renameTo Method:

To rename (or move) a file, call the method renameTo() on the File class. 

Usage:

File file = new File("c:\\temp\\text-file.txt"); 
boolean success = file.renameTo(new File("c:\\temp\\renamed-file.txt")); 

As briefly mentioned earlier, the renameTo() method can also be used to move a file to a different directory. The new file name passed to the renameTo() method does not have to be in the same directory as the file was already residing in.

The renameTo() method returns boolean (true or false), indicating whether the renaming was successful. Renaming of moving a file may fail for various reasons, like the file being open, wrong file permissions etc.


delete Method:

This method is used to delete a file or directory.

Usage:

The delete() method returns boolean (true or false), indicating whether the deletion was successful. Deleting a file may fail for various reasons, like the file being open, wrong file permissions etc.

Note: This method can only remove directory if it is empty, means no other files or directories in it. The directory must be clean.

File file = new File("c:\\temp\\text-file.txt"); 
boolean success = file.delete();


isDirectory Method:

You can check if a File object points to a file or directory, by calling its isDirectory() method. This method returns true if the File points to a directory, and false if the File points to a file.

Usage:

File file = new File("c:\\temp\\text-file.txt"); 
boolean isDirectory = file.isDirectory();


listFiles or list Method:

You can obtain a list of all the files in a directory by calling either the list() method or the listFiles() method.


The list() method returns an array of String's with the file and / or directory names of directory the File object points to.

The listFiles() returns an array of File objects representing the files and / or directories in the directory the File points to.

File object can be used to perform file operations where you cannot do the same on strings. Chose your method wisely according to the need.

Example: Create multiple text files and directories in the existing directory C:\\temp and run below program,

import java.io.File;
import java.io.IOException;

public class FilesDemo {

  public static void main(final String[] args) throws IOException {

    final File dir = new File("c:\\temp");
    // List the files in temp directory in string format
    final String[] fileNames = dir.list();
    for (final String fileName : fileNames) {
      System.out.println(fileName);
    }
    // List the files in temp directory in File object format
    final File[] files = dir.listFiles();
    for (final File file : files) {
      // File object can be used to perform file operations where you cannot do the same on strings
      System.out.println(file.isDirectory());
    }
  }
}

Output:
newdir
text-file - Copy.txt
text-file.txt
true
false
false


Parent and Child in Files:

Let's say you have a directory c:\\temp\\newdir. In this directory path c:\\temp becomes a parent and newdir becomes a child of the directory pathPreviously we were creating file instance like below,


File dir = new File("c:\\temp\\newdir");

File class also has another constructor which will allow you to create an instance of File with Parent and child instead full directory path in one argument.


File dir = new File("c:\\temp", "newdir");

The above will also applicable in case of a file where the file path is c:\\temp\\text-file.txt. In this file path c:\\temp becomes a parent and text-file.txt becomes a child. So you can create a File instance in the similar way of creating an instance for a directory.

File dir = new File("c:\\temp", "text-file.txt");

In both the cases the parent can be a File instance or just a string.


Now we know how to create a file, renaming it and deleting it. Let's learn how to read and write to files.

Before getting to know them first we must understand what is a Stream. It is nothing but a sequence of data. There are 2 stream where we use when we are doing I/O operations.


  • InputStream : used to read data from a source.
  • OutputStream : used for writing data to a destination.
Java provides verious stream readers or writers but most widely used streams are,

Byte Streams:

Byte streams are used to perform input and output operations and can read or write one byte at a time. There are many Java classes related to byte streams but the most frequently used classes are, FileInputStream and FileOutputStream. In following example we use these two classes to read from a file and write to different file,

To do this create a file called input-file.txt anywhere in your file system. I am creating it in c:\temp and write something in it. We are going to read the content you have written to the input-file.txt and write it to output-file.txt file.


import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class StreamsDemo {

  public static void main(final String args[]) throws IOException {

    try (FileInputStream in = new FileInputStream("C:\\temp\\input-file.txt");
        FileOutputStream out = new FileOutputStream("C:\\temp\\output-file.txt")) {
      int c;
      while ((c = in.read()) != -1) {
        out.write(c);
      }
    }
  }
}
Note: Above example uses try-with-resources implementation. You can follow post try-with-resources if you are new to it.

Execute above program and view the output-file.txt. You will find what you entered into input-file.txt

Character Streams:

Java Character streams are used to perform input and output for 16-bit unicode. Though there are many classes related to character streams but the most frequently used classes are, FileReader and FileWriter. Though internally FileReader uses FileInputStream and FileWriter uses FileOutputStream but here the major difference is that FileReader reads two bytes at a time and FileWriter writes two bytes at a time.

The key difference Byte stream and Character Streams i, InputSTream is that it reads binary data, one byte at a time. A Reader is for reading text and it decodes bytes into char using the character encoding you set or the default encoding e.g. UTF-8 can turn 1, 2 or 3 bytes into a single char.

Let's take above example and rewrite it using Charactor streams i.e. FileReader and FileWriter. Clear the content from the output-file.txt if something was already written to it.


import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class StreamsDemo {

  public static void main(final String args[]) throws IOException {

    try (FileReader reader = new FileReader("C:\\temp\\input-file.txt");
        FileWriter writer = new FileWriter("C:\\temp\\output-file.txt")) {
      int c;
      while ((c = reader.read()) != -1) {
        writer.write(c);
      }
    }
  }
}
Note: Above example uses try-with-resources implementation. You can follow post try-with-resources if you are new to it.

Execute above program and view the output-file.txt. You will find what you entered into input-file.txt.


Buffered I/O Streams:

Both BufferedReader and BufferedWriter in java are classified as buffered I/O streams.

BufferedReader is a class in Java that reads text from a character-input stream, buffering characters so as to provide for the efficient reading of characters, lines and arrays. The buffer size may be specified. If not, the default size, which is predefined, may be used.

So each read request made of a Reader causes a corresponding read request to be made of the underlying character or byte stream. It is therefore good practice to wrap a BufferedReader around any Reader whose read() operations may be costly, such as FileReaders and InputStreamReaders. 

For example,

FileReader reader = new FileReader(MyFile.txt);
BufferedReader bufferedReader = new BufferedReader(reader);

This will buffer the input from the specified file. Without buffering, each invocation of read() or readLine() could cause bytes to be read from the file, converted into characters, and then returned, which can be very inefficient.


BufferedWriter on the other hand is a java class that writes text to a character-output stream, while buffering characters so as to provide for the efficient writing of single characters, strings and arrays.

A newLine() method is provided, which uses the platform’s own notion of line separator as defined by the system property line.separator. Calling this method to terminate each output line is therefore preferred to writing a newline character directly.

In most occasions, a Writer sends its output immediately to the underlying character or byte stream. Unless prompt output is required, it is good practice to wrap a BufferedWriter around any Writer whose write() operations may be costly, such as FileWriters and OutputStreamWriters. 

For example,

File outputFile = new File("output.txt");
BufferedWriter bw = new BufferedWriter(new FileWriter(outputFile));

Let's rewrite the same above example with BufferedReader and BufferedWriter. Clear the content from the output-file.txt if something was already written to it.


import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class StreamsDemo {

  public static void main(final String args[]) throws IOException {

    try (BufferedReader reader = new BufferedReader(new FileReader("C:\\temp\\input-file.txt"));
        BufferedWriter writer = new BufferedWriter(new FileWriter("C:\\temp\\output-file.txt"))) {
      String line;
      while ((line = reader.readLine()) != null) {
        writer.write(line);
      }
    }
  }
}

Note: Above example uses try-with-resources implementation. You can follow post try-with-resources if you are new to it.

Execute above program and view the output-file.txt. You will find what you entered into input-file.txt.

No comments:

Post a Comment