o7planning

Java IO Character Streams Tutorial with Examples

  1. Introduction
  2. The difference between binary streams and character streams
  3. Overview of the character streams
  4. Class java.io.Reader
  5. Class java.io.Writer
  6. How a binary stream is converted into a character stream?
  7. Class java.io.BufferedReader
  8. Class java.io.BufferedWriter
  9. Class java.io.FilterReader
  10. Class java.io.FilterWriter
  11. Class java.util.PushbackReader
  12. Class java.io.PrintWriter
  13. Class java.io.CharArrayReader
  14. Class java.io.CharArrayWriter
  15. Class java.io.PipedReader
  16. Class java.io.PipedWriter

1. Introduction

In the previous instruction document, I introduced input-output binary stream. You need to understand it before studying input-output character stream. You can see here:

2. The difference between binary streams and character streams

Binary Stream, each one reads/writes a byte (equivalent to 8 bits)
Meanwhile, character stream read/write a character. It is dependent on type of encoding (UTF-8, UTF-16,...) to decide the number of bytes in each reading/writing turn which are 1 byte, 2 bytes, or 3 bytes. Let's see the following illustrated image:
UTF-16:
This is a Japanese text. If it is stored in a File encoded UTF-16, bytes in hard disk drive will be similar to the illustrated image:
  • Two first bytes (254,255) mean notifying the beginning of a String with UTF-16 encoding.
  • The next characters are encoded by 2 bytes.
    • For example, 'J' character is encoded by 2 bytes (0 and 74)
    • 'P' character is encoded by 2 bytes (0 and 80)
    • .....
  • When reading from file with UTF-16 encoding, it will ignore two first bytes and read two consecutive bytes into one character.
UTF-8:
It will be different if the same above-mentioned Japanese text is encoded by UTF-8. You can see that bytes are stored in hard disk drive:
  • With ASCII characters, it will only use one byte for storage.
    • For example, it takes 1 byte to store 'J' character (74)
    • It takes 1 byte to store 'P' character (80)
  • It may take 2 bytes or 3 bytes to store other characters.
  • In the rule of reading, base on a UTF-8 Table.
    • Read the first byte, if it <= 127, then it's an ASCII character.
    • Else if it >127, then it needs to read the second byte, and check whether two bytes can be combined into one character based on the UTF-8 Table.
    • If the first 2 bytes do not correspond to 1 character, It will read the next byte and combine them into a character.
    • UTF-8 uses up to 3 bytes to store a character.

To sum up, when you save a document with any encoding, you need to read with an equivalent encoding, or else the output of reading will be wrong.

3. Overview of the character streams

Hierarchies of Classes:

4. Class java.io.Reader

Reader is a abstract class. it is the base class for character reading streams.
Create a file test_reader.txt to start an example with Reader:
HelloReader.java
package org.o7planning.tutorial.javaio.readerwriter;

import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

public class HelloReader {

	public static void main(String[] args) throws IOException {
		// Create a Reader (Character stream), to read a file.
		// With default encoding.
		Reader r = new FileReader("test_reader.txt");
		int i = -1;

		// Read each character in turn.
		while ((i = r.read()) != -1) {
			// Cast to char.
			System.out.println((char) i);
		}
		r.close();
	}

}
Run the example:
The next example is to read many characters in a reading turn. This helps enhance the efficiency of the program compared to reading each character in turn.
HelloReader2.java
package org.o7planning.tutorial.javaio.readerwriter;

import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

// This example, read multi characters in once.
public class HelloReader2 {

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

		// Create a Reader, to read a file.
		// With default encoding.	
		Reader r = new FileReader("test_reader.txt");
		// Create temporary array of characters.
		char[] temp = new char[10];
		int i = -1;

		// read(char[]) method:
		// Read multiple characters at once, 
		// and assign them to the elements of the array.
		// Return the number of characters read.
		// Or returns -1 if the end of the stream has been reached. 
		while ((i = r.read(temp)) != -1) {
			String s = new String(temp, 0, i);
			System.out.println(s);
		}
		r.close(); 
	}

}

5. Class java.io.Writer

Writer is an abstract class, it is the base class for the character writing stream.
HelloWriter.java
package org.o7planning.tutorial.javaio.readerwriter;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

public class HelloWriter {

	public static void main(String[] args) throws IOException {
		File dir = new File("C:/test");

		// Create 'C:/test' directory, if it does not exists.
		dir.mkdirs();

		// Create a Writer, to write data to the file.
		// Using default encoding.
		Writer w = new FileWriter("C:/test/test_writer.txt");

		// Array of characters.
		char[] chars = new char[] { 'H', 'e', 'l', 'l', 'o', // 
				' ', 'w', 'r', 'i', 't', 'e', 'r' };

		// Write characters to stream.
		for (int i = 0; i < chars.length; i++) {
			char ch = chars[i];
			int j = (int) ch;
			// 
			w.write(j);
		}
		// Close stream,
		w.close();
	}
}
Results of running the example:
The next example is to write many characters in a stream at the same time. Specifically, we write an array of characters into a stream. This helps enhance the efficiency of the program compared to writing each character in turn.
HelloWriter2.java
package org.o7planning.tutorial.javaio.readerwriter;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

public class HelloWriter2 {

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

		File dir = new File("C:/test");
		// Create 'C:/test' directory, if it does not exists.
		dir.mkdirs();

		// Create a Writer, to write the data to the file.
		Writer w = new FileWriter("C:/test/test_writer2.txt");

		// 
		char[] chars = new char[] { 'H', 'e', 'l', 'l', 'o', //
				' ', 'w', 'r', 'i', 't', 'e', 'r' };

		// Write all characters to the stream.
		w.write(chars);

		// Java often uses buffers to store data temporarily.
		// When the buffer is full, it flush the data to the file.
		// You can proactively flush data into the file.
		w.flush();

		// Write 'new line' character to stream.
		w.write('\n');

		String s = "FileWriter";

		// Write a String to stream.
		w.write(s);

		// Close stream.
		// It will push the data in buffer to the file.
		// Also finish writing data.
		w.close();
	}
}
Results of running the example:

6. How a binary stream is converted into a character stream?

You have a binary stream. And you want to convert it into a character stream?
In the above examples, we get accustomed with Reader and Writer. The next example allows you actively to read and write in the stream with a clearly specified encoding.
Create file test_utf8.txt
test_utf8.txt
JP日本-八洲
When you save, eclipse will ask you what type of encoding you want to save. Select UTF-8
InputStreamReaderExample.java
package org.o7planning.tutorial.javaio;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;

public class InputStreamReaderExample {

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

		// Create binary stream, read a file.
		InputStream in = new FileInputStream("test_utf8.txt");

		// Create character stream wrap binary stream above.
		// Encoding UTF-8
		Reader reader = new InputStreamReader(in, "UTF-8");

		int i = 0;
		// Read turn each character.
		while ((i = reader.read()) != -1) {
			// cast int to char, and print to the Console.
			System.out.println((char) i + " " + i);
		}
		reader.close();
	}
}
Results of running the example
The next example, write file encoded with UTF-8.
OutputStreamWriterExample.java
package org.o7planning.tutorial.javaio;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;

public class OutputStreamWriterExample {

	public static void main(String[] args) throws IOException {
		
		File dir = new File("C:/test");
		// Create 'C:test' directory if it does not exists.
		dir.mkdirs();
		// Create a OutputStream, to write data to a file.
		OutputStream out = new FileOutputStream("C:/test/test_write_utf8.txt");

		// Create character stream wrap a OutputStream above.
		// encoding UTF-8.
		Writer writer = new OutputStreamWriter(out, "UTF-8");

		String s = "JP日本-八洲";
		writer.write(s);
		writer.close();
	}

}
Results of running the example

7. Class java.io.BufferedReader

If you want to read each line of data of a text file. BufferedReader is a good choice.
// BufferedReader is a direct subclass of Reader.
// Constructor:
public BufferedReader(Reader in);

// A convenient method of BufferedReader.
// Read a line of text.
public String readLine();
Ví dụ:
// Example 1:
Reader r=new FileReader("C:/test.txt");
BufferedReader br=new BufferedReader(r);

// Example 2:
InputStream in = new FileInputStream("C:/test.txt");
Reader r = new InputStreamReader(in, "UTF-8");
BufferReader br = new BufferedReader(r);
test_multi_lines.txt
## Fruit List
Apricots
Barbados Cherries
Bitter Melon
Cherimoya
Honeydew
Jackfruit
Limes
Lychee
Mango
Oranges
Pineapple
Strawberries
BufferedReaderExample.java
package org.o7planning.tutorial.javaio.buffered;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;

public class BufferedReaderExample {

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

		InputStream in = new FileInputStream("test_multi_lines.txt");
		Reader reader = new InputStreamReader(in, "UTF-8");
		BufferedReader br = new BufferedReader(reader);

		String s = null;
		int i = 0;

		// Read each line of data
		// If returns null means ending stream.
		while ((s = br.readLine()) != null) {
			i++;
			System.out.println(i + " : " + s);
		}
		br.close();
	}

}
Results of running the example:

8. Class java.io.BufferedWriter

BufferedWriter is a direct subclass of the Writer class.
// Create a BufferedWriter object 
// by wrapping another Writer object.
public BufferedWriter(Writer out);

// Equivalent to write ('\ n');
public String newLine();
Ví dụ:
// Create Writer object.
Writer w=new FileWriter("C:/test/test_bufferedWriter.txt");

// Create BufferedWriter object wrap a writer.
BufferedWriter bw=new BufferedWriter(w);

bw.write("Hello..");

// Write a new line character.
bw.newLine();

9. Class java.io.FilterReader

FilterReader is a subclass of Reader. It reads selectively characters on demand. For example, you want to read an HTML document, and ignore the characters in the tags. You need to write a subclass of FilterReader and then use that subclass. You cannot directly use FilterReader since it is a abstract class.
Example, create a subclass of FilterReader, to read HTML document but ignore characters in tag.
Input: "<h1>Hello</h1>" ==> output: "Hello".
RemoveHTMLReader.java
package org.o7planning.tutorial.javaio.filter;

import java.io.FilterReader;
import java.io.IOException;
import java.io.Reader;

public class RemoveHTMLReader extends FilterReader {

	boolean intag = false;

	public RemoveHTMLReader(Reader in) {
		super(in);
	}

	// Override this method.
	// The principle would be:
	// Only read characters outside the tags.
	@Override
	public int read(char[] buf, int from, int len) throws IOException {

		int charCount = 0;

		while (charCount == 0) {

			charCount = super.read(buf, from, len);
			if (charCount == -1) {
				// End the stream.
				return -1;
			}

			int last = from;

			for (int i = from; i < from + charCount; i++) {
				// If not in an HTML tag.
				if (!intag) {
					if (buf[i] == '<') {
						intag = true;
					} else {
						buf[last++] = buf[i];
					}
				} else if (buf[i] == '>') {
					intag = false;
				}
			}

			charCount = last - from;
		}
		return charCount;
	}

	// Override this method too.
	@Override
	public int read() throws IOException {
		char[] buf = new char[1];
		int result = read(buf, 0, 1);
		if (result == -1) {
			return -1;
		} else {
			return (int) buf[0];
		}
	}
}
RemoveHTMLReaderTest.java
package org.o7planning.tutorial.javaio.filter;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;

public class RemoveHTMLReaderTest {

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

		// Create Reader object from StringReader constructor.
		Reader in = new StringReader("<h1>Hello \n <b>World</b><h1>");

		RemoveHTMLReader filterReader = new RemoveHTMLReader(in);
		BufferedReader br = new BufferedReader(filterReader);

		String s = null;
		while ((s = br.readLine()) != null) {
			System.out.println(s);
		}
		br.close();
	}
}
Results of running the example:

10. Class java.io.FilterWriter

FilterWriter is a direct subclass of Writer. It writes selectively characters on demand. You need to write a subclass of FilterWriter and override some methods of the FilterWriter class.
Example: Characters changed when writing to stream.
Rot13.java
package org.o7planning.tutorial.javaio.filter;

public class Rot13 {
    
    /**
     * <pre>
     *   a ==> n
     *   b ==> o
     *   c ==> p
     *   d ==> q
     *   e ==> r
     *   ...
     *   y ==> l
     *   z ==> m
     * </pre>
     */
    public static int rotate(int inChar) {
        int outChar;
        
        if (inChar >= (int) 'a' && inChar <= (int) 'z') {
            outChar = (((inChar - 'a') + 13) % 26) + 'a';
        } else if (inChar >= (int) 'A' && inChar <= (int) 'Z') {
            outChar = (((inChar - 'A') + 13) % 26) + 'A';
        } else {
            outChar = inChar;
        }
        return outChar;
    }
    
    // Test
    public static void main(String[] args)  {
        for(char ch='a'; ch<='z';ch++ ) {
            char m= (char)rotate(ch);
            System.out.println("ch="+ch+" ==> "+ m);    
        }      
        
    }
}
RotateWriter.java
package org.o7planning.tutorial.javaio.filter;

import java.io.FilterWriter;
import java.io.IOException;
import java.io.Writer;

public class RotateWriter extends FilterWriter {
 
	public RotateWriter(Writer out) {
		super(out);
	}

	// override one or more write methods to perform filtering.
	// (override both to be safe) 
	@Override
	public void write(int outChar) throws IOException {
		super.write(Rot13.rotate(outChar));
	}

	@Override
	public void write(char[] cbuf, int offset, int length) throws IOException {
		char[] tempbuf = new char[length];
		for (int i = 0; i < length; i++) {
			tempbuf[i] = (char) Rot13.rotate(cbuf[offset + i]);
		}
		super.write(tempbuf, 0, length);
	}

}
RotateWriterTest.java
package org.o7planning.tutorial.javaio.filter;

import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;

public class RotateWriterTest {

    
    public static void main(String[] args) throws IOException  {
        String s="abcdef";
        
        Writer writer= new StringWriter();
        
        RotateWriter rw= new RotateWriter(writer);
        rw.write(s.toCharArray(),0,s.length());
        
        rw.close();
        
        String rotateString = writer.toString();
        System.out.println("rotateString="+ rotateString);
    }
}
Results of running the example:

11. Class java.util.PushbackReader

The PushbackReader class allows one or more characters to be returned to the stream after reading them. Here are its two constructors:
public PushbackReader(Reader inputStream)

public PushbackReader(Reader inputStream, int bufSize)
Some additional methods:
// Pushes back a single character to stream.
public void unread(int c) throws IOException
Example:
PushbackReaderDemo.java
package org.o7planning.tutorial.javaio.pushback;

import java.io.CharArrayReader;
import java.io.IOException;
import java.io.PushbackReader;

class PushbackReaderDemo {

	public static void main(String args[]) throws IOException {
		String s = "if (a == 4) a = 0;\\n";
		char buf[] = new char[s.length()];
		s.getChars(0, s.length(), buf, 0);
		CharArrayReader in = new CharArrayReader(buf);
		PushbackReader f = new PushbackReader(in);
		int c;
		while ((c = f.read()) != -1) {
			switch (c) {
			// Found character '='
			case '=':
				// Read next character, (after found '=')
				if ((c = f.read()) == '=') {
					System.out.print(".eq.");
				}

				else {
					System.out.print("<-");
					// Pushes back a single character by copying it to
					// the front of the pushback buffer.
					// (like - move the cursor back one position).
					f.unread(c);
				}
				break;
			default:
				System.out.print((char) c);
				break;
			}
		}
	}

}
Results of running the example:

12. Class java.io.PrintWriter

// Constructor:
// Wrap a Writer object.
public PrintWriter(Writer out) 
public PrintWriter(Writer out,boolean autoFlush)

// Wrap a OutputStream object.
public PrintWriter(OutputStream out) 
public PrintWriter(OutputStream out,boolean autoFlush)
public PrintWriter(String fileName)
...

// Method:
public void println(String s)
public void print(char ch)
StackTraceToFile.java
package org.o7planning.tutorial.javaio.printwriter;

import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.io.Writer;

public class StackTraceToFile {

	public static void main(String[] args) {
		try {
			// Do something here.
			// Error divided by 0.
			int i = 10 / 0;
		} catch (Exception e) {
			System.out.println("EXCEPTION ....");
			try {
				File dir = new File("C:/test");
				// Create directories if it not exists.
				dir.mkdirs();
				// Create stream to write data to the file.
				Writer w = new FileWriter("C:/test/stackTrace.txt");
				
				// Create PrintWriter object wrap Writer 'w'.
				// Data written to the PrintWriter will be pushed into 'w'.
				PrintWriter pw = new PrintWriter(w);

				// Write 'stack trace' to 'pw'.
				e.printStackTrace(pw);
				System.out.println("Finish !");
			} catch (Exception e1) {
				System.out.println("Error:" + e);
			}
		}
	}

}
StackTraceToString.java
package org.o7planning.tutorial.javaio.printwriter;

import java.io.PrintWriter;
import java.io.StringWriter;

public class StackTraceToString {

	public static void main(String[] args) {
		try {
			// Do something here
			// Error divided by 0.
			int i = 1000 / 0;
		} catch (Exception e) {
			System.out.println("EXCEPTION ....");
			try {
				StringWriter sw = new StringWriter();
				// Create PrintWriter object wrap StringWriter 'sw'.
				// Data written to the PrintWriter will be pushed into 'sw'.
				PrintWriter pw = new PrintWriter(sw);

				// Write 'stack trace' to 'pw'.
				e.printStackTrace(pw);

				StringBuffer sb = sw.getBuffer();
				String s = sb.toString();
				System.out.println("Exception String:");
				System.out.println(s);
			} catch (Exception e1) {
				System.out.println("Error:" + e);
			}
		}

	}

}
Results of running the example:

13. Class java.io.CharArrayReader

CharArrayReaderDemo.java
package org.o7planning.tutorial.javaio.chararray;

import java.io.CharArrayReader;
import java.io.IOException;

public class CharArrayReaderDemo {
    
    public static void main(String args[]) throws IOException {
        
        String tmp = "abcdefghijklmnopqrstuvwxyz";
        int length = tmp.length();
        char c[] = new char[length];
        tmp.getChars(0, length, c, 0);
        
        CharArrayReader input1 = new CharArrayReader(c);
        CharArrayReader input2 = new CharArrayReader(c, 0, 5);
        
        int i;
        System.out.println("input1 is:");
        while ((i = input1.read()) != -1) {
            System.out.print((char) i);
        }
        System.out.println();
        System.out.println("input2 is:");
        while ((i = input2.read()) != -1) {
            System.out.print((char) i);
        }
        System.out.println();
    }
}
Results of running the example:

14. Class java.io.CharArrayWriter

Some additional methods:
// Writes the contents of the buffer to another character stream.
public void writeTo(Writer out) throws IOException
CharArrayWriterDemo.java
package org.o7planning.tutorial.javaio.chararray;

import java.io.CharArrayWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

public class CharArrayWriterDemo {

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

		char[] c = { 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!' };
		CharArrayWriter out = new CharArrayWriter();

		out.write(c);

		File dir = new File("C:/test");
		dir.mkdirs();

		FileWriter f1 = new FileWriter(new File("C:/test/a.txt"));

		// Write data of 'out' to 'f1'.
		out.writeTo(f1);

		FileWriter f2 = new FileWriter(new File("C:/test/b.txt"));

		// Write data of 'out' to 'f2'.
		out.writeTo(f2);

		f1.close();
		f2.close();

		// Close CharArrayWriter 'out'.
		out.close();

		FileWriter f3 = new FileWriter(new File("C:/test/c.txt"));

		// With CharArrayWriter, after close.
		// writeTo(..) method no longer works.
		// Also does not cause an exception if you use writeTo (..).
		out.writeTo(f3);

		System.out.println("Done!");
	}
}

15. Class java.io.PipedReader

  • TODO
PipeReaderExample1.java
package org.o7planning.tutorial.javaio.pipereader;

import java.io.IOException;
import java.io.Reader;
import java.io.PipedReader;
import java.io.PipedWriter;

public class PipeReaderExample1 {

	private Reader pipedReader;

	public static void main(String[] args) throws IOException, InterruptedException {
		new PipeReaderExample1().test();
	}

	private void test() throws IOException, InterruptedException {
		// Create a 'pipedWriter',
		PipedWriter pipedWriter = new PipedWriter();

		// Data writing to 'pipedWriter'
		// will automatically appear in 'pipedReader'.
		pipedReader = new PipedReader(pipedWriter);

		new ThreadRead().start();

		char[] chs = new char[] { 'a', 'a', 'b', 'c' , 'e' };

		// Write data to 'pipedWriter'.
		for (char ch : chs) {
			pipedWriter.write(ch);
			Thread.sleep(1000);
		}
		pipedWriter.close();
	}

	// A Thread to read the data that appears on 'pipedReader'.
	class ThreadRead extends Thread {

		@Override
		public void run() {
			try {
				int data = 0;
				while ((data = pipedReader.read()) != -1) {
					System.out.println((char) data);
				}
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				closeQuietly(pipedReader);
			}
		}
	}

	private void closeQuietly(Reader is) {
		if (is != null) {
			try {
				is.close();
			} catch (IOException e) {
			}
		}
	}

}
PipeReaderExample2.java
package org.o7planning.tutorial.javaio.pipereader;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.PipedReader;
import java.io.PipedWriter;
import java.io.Reader;

public class PipeReaderExample2 {

	private BufferedReader bufferedReader;

	public static void main(String[] args) throws IOException, InterruptedException {
		new PipeReaderExample2().test();
	}

	private void test() throws IOException, InterruptedException {
		// Create a 'pipedWriter',
		PipedWriter pipedWriter = new PipedWriter();

		// Data writing to 'pipedWriter'
		// will automatically appear in 'pipedReader'.
		PipedReader pipedReader = new PipedReader(pipedWriter);
		
		// Tạo một 'bufferedReader' wrapped 'pipedReader'.
		bufferedReader = new BufferedReader(pipedReader);

		new ThreadRead().start();

		String[] strs = new String[] { "Hello ", "There", "\n", "I am ", "Tran" };

		// Write data to 'pipedWriter'.
		for (String str : strs) {
			pipedWriter.write(str);
			Thread.sleep(500);
		}
		pipedWriter.close();
	}

	// A Thread to read the data that appears on 'bufferedReader' ('pipedReader').
	class ThreadRead extends Thread {

		@Override
		public void run() {
			try {
				String line = null;
				while ((line = bufferedReader.readLine()) != null) {
					System.out.println(line);
				}
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				closeQuietly(bufferedReader);
			}
		}
	}

	private void closeQuietly(Reader reader) {
		if (reader != null) {
			try {
				reader.close();
			} catch (IOException e) {
			}
		}
	}

}

16. Class java.io.PipedWriter

Java IO Tutorials

Show More