Java I/O Fundamentals

Read and write data from the console

Console object

Access to the console depends upon the underlying platform and also upon the way in which the Java program is invoked. If it's started from the command line without redirecting the standard input and output streams, then its console will exist. If it's stated for example by a background job scheduler or an IDE, it's most likely that it will be no access to the console.

If there's a console, it will be available with the System.console() method. If it's not available, an invocation of that method will return null.

Reading a line of text from the console:

Console console = null;
String s = null;
try
{
   console = System.console();
   if (console != null)
   {
      s = console.readLine();
      System.out.println(s);
   }
} catch (Exception ex)
{
   ex.printStackTrace();
}

For reading a password or other secure data,readPassword() or readPassword(String, Object...) (that provides a formatted prompt) and manually zero the returned character array after processing to minimize the lifetime of sensitive data in memory:

Console console = null;
char[] passwd = null;
try
{
   console = System.console();
   if (console != null)
   {
      if((passwd = console.readPassword("[%s]", "Password:")) != null) {
        java.util.Arrays.fill(passwd, ' ');
      }
   }
} catch (Exception ex)
{
   ex.printStackTrace();
}

For writing, we have two equivalent methods that accept a format string:

Console console = System.console();
if (console != null)
{
  console.format("[%s]", "Hi");
  console.printf("[%s]", "Hi again");
  console.format("Or just hi");
}

Standard Streams

Java supports three standard streams: Standard Input, accessed through System.in; Standard Output, accessed through System.out; and Standard Error, accessed through System.err. These objects are defined automatically and do not need to be opened.

To read using streams:

try {
   BufferedReader bufferRead = new BufferedReader(new InputStreamReader(System.in));
   String s = bufferRead.readLine();

   System.out.println(s);
}
catch(IOException ex)
{
  ex.printStackTrace();
}

To write, standard output and standard error are both for output and they are defined as PrintStream objects:

System.out.println("Hi");
System.out.print("Hi again\n");

 

Use BufferedReader, BufferedWriter, File, FileReader, FileWriter, FileInputStream, FileOutputStream, ObjectOutputStream, ObjectInputStream, and PrintWriter in the java.io package.

File

This class is a representation of a file or a directory pathnames. Its instances are immutable, that is, once created, the abstract pathname represented by the object will never change.

You can create an instance this way:

File file = new File("c:\\file.txt");

Or:

File file = new File("/usr/file.txt");

Once you have created a File object you can do a lot of things:

// Check if the corresponding file or directory actually exists
boolean fileExists = file.exists();

// Create a single directory if it does not already exist
boolean directoryCreated = file.mkdir();

// Read the length of the file in bytes
long length = file.length();

// Rename or move a file or directory:
boolean renameSuccessful = file.renameTo(new File("c:\\new-file.txt"));

// Delete the file or directory
success = file.delete();

// Check if the File object points to a directory
boolean isDirectory = file.isDirectory();

// Check if the file/directory is hidden
boolean isHidden = file.isHidden();

// Get a list (an array) of all the names of the files/directories in a directory
String[] fileNames = file.list();

// Get a list of all files/directories in a directory as instances of File
File[]   files = file.listFiles();

FileReader
and
FileWriter

FileReader and FileWriter are character based, they are intended for reading and writing text.

Here's an example code snippet for FileReader:

Reader reader = new FileReader("c:\\file.txt");
int data = reader.read();
while(data != -1){
    char dataChar = (char) data;
    data = reader.read();
}
reader.close();

Here's an example code snippet for FileWriter:

Writer writer = new FileWriter("c:\\file.txt");
writer.write("Hello World Writer");
writer.close();

FileReader extends from InputStreamReader, so it can work with an InputStream. At the same time, FileWriter extends from OutputStreamReader, so it can work with an OutputStream.

FileInputStream

FileInputStream reads the contents of a file as a stream of bytes. It's a subclass of InputStream. It can be created either with a String or a File object that represent a path. Here's an example:

InputStream input = new FileInputStream("c:\\text.txt");
int byteData = input.read();
while(byteData != -1) {
  byteData = input.read();
}
input.close();

There's another version of read() that reads up to the length of an array of bytes of data from the input stream into that array:

InputStream fis = new FileInputStream("c:\\text.txt");
byte[] data = new byte[1024];
int bytesRead = fis.read(data);
while(bytesRead != -1) {
  bytesRead = fis.read(data);
}
fis.close();

FileOutputStream

FileOutputStream writes the contents of a file as a stream of bytes. It's a subclass of OutputStream. It can be created either with a String or a File object that represent a path.

When you create a FileOutputStream representing a file that already exists, you can decide if you want to overwrite or to append to the existing file. It depends on the constructor you choose:

OutputStream fos1 = new FileOutputStream("c:\\text.txt"); //overwrites file
OutputStream fos2 = new FileOutputStream("c:\\text.txt", true); //appends to file
OutputStream fos3 = new FileOutputStream("c:\\text.txt", false); //overwrites file

When you write to a FileOutputStream, the data may get cached internally in memory and written to disk at a later time. If you want to make sure that all data is written to disk without having to close the FileOutputStream, you can call its flush() method.

OutputStream output = null;
try {
  output = new FileOutputStream("c:\\text.txt");

  while(moreData()) {
    int data = getData();
    output.write(data);
  }
} finally {
    if(output != null) {
        output.close();
    }
}

The other versions of the write() method are: write(byte[] bytes). It writes all the bytes in the byte array to the OutputStream. write(byte[] bytes, int offset, int length). It writes to the OutputStream length number of bytes starting from an offset of the byte array.

BufferedReader

BufferedReader provides buffering to a character-input stream. Rather than read one byte at a time, BufferedReader reads a larger block at a time. To add buffering to an InputStream just wrap it in a BufferedInputStream:

Reader r = new BufferedReader(new FileReader("c:\\file.txt"));

The BufferedReader creates a byte array internally and fills it by calling the read() or readLine() methods on the underlying Reader. You can set the buffer size to use internally, for example to 1024 bytes, like this:

Reader r = new BufferedReader(new FileReader("c:\\file.txt"), 1024);

BufferedWriter

BufferedWriter provides buffering to a character-output stream. To add buffering to a Writer just wrap it in a BufferedWriter:

BufferedWriter input = new BufferedWriter(new FileWriter("c:\\file.txt"));

To set the size of the buffer, provide it as a constructor parameter like this:

BufferedWriter input = new BufferedWriter(new FileWriter("c:\\file.txt"), 1024);

Without buffering, each invocation of a write() or newLine() method would cause characters to be converted into bytes and written immediately to the file, which can be very inefficient.

ObjectInputStream

ObjectInputStream allows you to read serialized objects (their class must implement java.io.Serializable) from an InputStream instead of only bytes. You wrap an InputStream in an ObjectInputStream like this:

class Test implements java.io.Serializable {}
...
ObjectInputStream input = new ObjectInputStream(new FileInputStream("obj.data"));
Test object = (Test) input.readObject();
input.close();

ObjectOutputStream

ObjectOutputStream allows you to write serialized objects (their class must implement java.io.Serializable) from an OutputStream instead of only bytes. You wrap an OutputStream in an ObjectOutputStream like this:

class Test implements java.io.Serializable {}
...
ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream("obj.data"));
Test object = new Test();
output.writeObject(object);
output.close();

PrintWriter

PrintWriter class allows you to write formatted data or data from primitive types instead of bytes to an underlying Writer. Here's an example:

PrintWriter writer = new PrintWriter(new FileWriter("c:\\file.txt") );
writer.print(true);
writer.print(1);
writer.print(1.23);

// printf and format methods do the same
writer.printf("%s", "Hi");
writer.format("%s", "Hi");

writer.close();

The constructors of PrintWriter are:

PrintWriter(File file)
Creates a new PrintWriter, without automatic line flushing, with the specified file.

PrintWriter(File file, String csn)
Creates a new PrintWriter, without automatic line flushing, with the specified file and charset.

PrintWriter(OutputStream out) `
Creates a new PrintWriter, without automatic line flushing, from an existing OutputStream.

PrintWriter(OutputStream out, boolean autoFlush)
Creates a new PrintWriter from an existing OutputStream.

PrintWriter(String fileName)
Creates a new PrintWriter, without automatic line flushing, with the specified file name.

PrintWriter(String fileName, String csn)
Creates a new PrintWriter, without automatic line flushing, with the specified file name and charset.

PrintWriter(Writer out)
Creates a new PrintWriter, without automatic line flushing.

PrintWriter(Writer out, boolean autoFlush)
Creates a new PrintWriter.

 

Content