I have already covered the basics of Java I/O in my Files and Steams section, it times to cover other I/O classes. I/O sources can be files, memory buffers, network conenctions, etc and to handle all these types of I/O Java abstracts them into a stream, an I/O stream is linked to a physical device by the Java I/O system. There is also the New I/O (NIO) which is a second feature that deals with I/O and I will be discussing this in the next section, althrough being better in performance NIO is not used as much as Java I/O.
I am going to cover most of the Classes and Interfaces and will give brief introduction and examples of many of the commonly used ones and will leave you to investigate further any that I don't cover in depth.
There are many I/O Classes and Interfaces below is a table there are two deprecated classes LineNumberInputStream and StringBufferInputStream
I/O Classes | ||
BufferedInputStream | FileWriter | PipedOutputStream |
BufferedOutputStream | FilterInputStream | PipedReader |
BufferedReader | FilterOutputStream | PipedWriter |
BufferedWriter | FilterReader | PrintStream |
ByteArrayInputStream | FilterWriter | PrinterWriter |
ByteArrayOutputStream | InputStream | PushbackInputStream |
CharArrayReader | InputStreamReader | PushbackReader |
CharArrayWriter | LineNumberReader | RandomAccessFile |
Console | ObjectInputStream | Reader |
DataInputStream | ObjectInputStream.GetField | SequenceInputStream |
DataOutputStream | ObjectOutputStream | SerailizablePermission |
File | ObjectOutputStream.PutField | StreamTokenizer |
FileDescriptor | ObjectStreamClass | StringReader |
FileInputStream | ObjectStreamField | StringWriter |
FileOutputStream | OutputStream | Writer |
FilePermission | OutputStreamWriter | |
FileReader | PipedInputStream | |
I/O Interfaces | ||
Closable | FileFilter | ObjectInputValidation |
DataInput | FilenameFilter | ObjectOutput |
DataOutput | Flushable | ObjectStreamContants |
Externalizable | ObjectInput | Serializable |
The File class does not operate on streams, it deals directly with the file and filesystem. A File object is used to retrieve information from a file, including file permissions, time, date and directory path, note that directories in Java are treated simply as a file with an additional property that allows it to list files. Below are some examples on what you can do with the File class however there are many more methods than below:
File examples | File f1 = new File("FileTest.java"); System.out.println("File Name: " + f1.getName()); System.out.println("Path: " + f1.getPath()); System.out.println("Abs Path: " + f1.getAbsolutePath()); System.out.println("Parent: " + f1.getParent()); System.out.println(f1.exists() ? "exists" : "does not exist"); System.out.println(f1.canWrite() ? "is writeable" : "is not writeable"); System.out.println(f1.canRead() ? "is readable" : "is not readable"); System.out.println("is " + (f1.isDirectory() ? "" : "not" + " a directory")); System.out.println(f1.isFile() ? "is normal file" : "might be a named pipe"); System.out.println(f1.isAbsolute() ? "is absolute" : "is not absolute"); System.out.println("File last modified: " + f1.lastModified()); System.out.println("File size: " + f1.length() + " Bytes"); Output ------------------------------------------------------- File Name: FileTest.java Path: FileTest.java Abs Path: C:\java_projects\playingaround\FileTest.java Parent: null does not exist is not writeable is not readable is not a directory might be a named pipe is not absolute File last modified: 0 File size: 0 Bytes |
A directory is a File which contains a list of files and other directories, basically the same features for File can be used with one addition, you can list.
Directories examples | String dirname = "."; File f1 = new File(dirname); if (f1.isDirectory()) { System.out.println("Directory of " + dirname); for (String s: f1.list()){ File f = new File(dirname + "/" + s); // everything is a file if (f.isDirectory()) { System.out.println(s + " is a directory"); continue; } System.out.println(s + " is a file"); } } else { System.out.println(dirname + " is not a directory"); } Output ------------------------------------------ Directory of . .idea is a directory out is a directory playingaround.iml is a file src is a directory |
FilenameFilter example | class FilterExt implements FilenameFilter { String ext; public FilterExt(String ext){ this.ext = "." + ext; } public boolean accept(File dir, String name) { return name.endsWith(ext); } } Main ------------ String dirname = "src"; File f1 = new File(dirname); FilenameFilter onlyJava = new FilterExt("java"); for (String s: f1.list(onlyJava)) { System.out.println(s); } output ------------------ BitSetTest.java CalendarTest.java ConstructorRef1.java CurrencyTest.java DateTest.java ... |
Closing Files and Streams, Exceptions
There a few ways to close files and streams, it is important to access a file quickly, you should open it, do what you need to do then close it thus freeing its resource so that other parts of the problem can use it. There are three important interfaces that you know about:
There are two exceptions that play an important roile in I/O
There are two ways to close a stream, and you should be this as soon as possible failing to do this will cause memory leaks, and resource starvation.
close() statement | try { // open file and do stuff } catch (IOException) { } finally { // close the file stream....close() } |
try-with-resource example | try (resource-specification) { // use resource } --------------------------------------------- try (Scanner scanner = new Scanner(new File("test.txt"))) { \\ scanner implements Closable and AutoClosable while (scanner.hasNext()) { System.out.println(scanner.nextLine()); } } catch (FileNotFoundException fnfe) { fnfe.printStackTrace(); } |
Streams are based on a number of abstract classes InputStream and OutputStream (byte streams - use with bytes or binary objects), Reader and Writer (character streams - use with characters and strings), the FileInputStream class creates a InputStream that can be used to read bytes from a file, below is an example of this
FileInputStream examples | int size; // Use try-with-resources to close the stream. try ( FileInputStream f = new FileInputStream("src/FileInputStreamTest.java") ) { System.out.println("Total Available Bytes: " + (size = f.available())); int n = size/40; System.out.println("First " + n + " bytes of the file one read() at a time"); for (int i=0; i < n; i++) { System.out.print((char) f.read()); } System.out.println("\nStill Available: " + f.available()); System.out.println("Reading the next " + n + " with one read(b[])"); byte b[] = new byte[n]; if (f.read(b) != n) { System.out.println("couldn't read " + n + " bytes."); } System.out.println(new String(b, 0, n)); System.out.println("\nStill Available: " + (size = f.available())); System.out.println("Skipping half of remaining bytes with skip()"); f.skip(size/2); System.out.println("Still Available: " + f.available()); System.out.println("Reading " + n/2 + " into the end of array"); if (f.read(b, n/2, n/2) != n/2) { System.out.println("couldn't read " + n/2 + " bytes."); } System.out.println(new String(b, 0, b.length)); System.out.println("\nStill Available: " + f.available()); } catch(IOException e) { System.out.println("I/O Error: " + e); } Output ------------------------------ Total Available Bytes: 1726 First 43 bytes of the file one read() at a time import java.io.FileInputStream; import jav Still Available: 1683 Reading the next 43 with one read(b[]) a.io.IOException; public class FileInput Still Available: 1640 Skipping half of remaining bytes with skip() Still Available: 820 Reading 21 into the end of array a.io.IOException; dn't read " + n + " bt Still Available: 799 |
FileOutputStream Example | String source = "Now is the time for all good men\n to come to the aid of their country\n and pay their due taxes."; byte buf[] = source.getBytes(); FileOutputStream f0 = null; FileOutputStream f1 = null; FileOutputStream f2 = null; try { f0 = new FileOutputStream("file1.txt"); f1 = new FileOutputStream("file2.txt"); f2 = new FileOutputStream("file3.txt"); // write to first file for (int i=0; i < buf.length; i += 2) f0.write(buf[i]); // write to second file f1.write(buf); // write to third file f2.write(buf, buf.length-buf.length/4, buf.length/4); } catch(IOException e) { System.out.println("An I/O Error Occured"); } finally { try { if(f0 != null) f0.close(); } catch(IOException e) { System.out.println("Error Closing file1.txt"); } try { if(f1 != null) f1.close(); } catch(IOException e) { System.out.println("Error Closing file2.txt"); } try { if(f2 != null) f2.close(); } catch(IOException e) { System.out.println("Error Closing file3.txt"); } } |
ByteArrayInputStream | String tmp = "abcdefghijklmnopqrstuvwxyz"; byte b[] = tmp.getBytes(); ByteArrayInputStream input1 = new ByteArrayInputStream(b); ByteArrayInputStream input2 = new ByteArrayInputStream(b,0,3); |
ByteArrayOutputStream | ByteArrayOutputStream f = new ByteArrayOutputStream(); String s = "This should end up in the array"; byte buf[] = s.getBytes(); try { f.write(buf); } catch(IOException e) { System.out.println("Error Writing to Buffer"); return; } System.out.println("Buffer as a string"); System.out.println(f.toString()); System.out.println("Into array"); byte b[] = f.toByteArray(); for (int i=0; i < b.length; i++) System.out.print((char) b[i]); System.out.println("\nTo an OutputStream()"); // Use try-with-resources to manage the file stream. try ( FileOutputStream f2 = new FileOutputStream("test.txt") ) { f.writeTo(f2); } catch(IOException e) { System.out.println("I/O Error: " + e); return; } System.out.println("Doing a reset"); f.reset(); for (int i=0; i < 3; i++) f.write('X'); System.out.println(f.toString()); |
BufferedInputStream | String s = "This is a © copyright symbol but this is © not.\n"; byte buf[] = s.getBytes(); ByteArrayInputStream in = new ByteArrayInputStream(buf); int c; boolean marked = false; // Use try-with-resources to manage the file. try ( BufferedInputStream f = new BufferedInputStream(in) ) { while ((c = f.read()) != -1) { switch(c) { case '&': if (!marked) { f.mark(32); marked = true; } else { marked = false; } break; case ';': if (marked) { marked = false; System.out.print("(c)"); } else System.out.print((char) c); break; case ' ': if (marked) { marked = false; f.reset(); System.out.print("&"); } else System.out.print((char) c); break; default: if (!marked) System.out.print((char) c); break; } } } catch(IOException e) { System.out.println("I/O Error: " + e); } |
BufferedOutputStream | ByteArrayOutputStream f = new ByteArrayOutputStream(); String s = "This should end up in the array"; byte buf[] = s.getBytes(); try { f.write(buf); } catch(IOException e) { System.out.println("Error Writing to Buffer"); return; } System.out.println("Buffer as a string"); System.out.println(f.toString()); System.out.println("Into array"); byte b[] = f.toByteArray(); for (int i=0; i < b.length; i++) System.out.print((char) b[i]); System.out.println("\nTo an OutputStream()"); // Use try-with-resources to manage the file stream. try ( FileOutputStream f2 = new FileOutputStream("test.txt") ) { f.writeTo(f2); } catch(IOException e) { System.out.println("I/O Error: " + e); return; } System.out.println("Doing a reset"); f.reset(); for (int i=0; i < 3; i++) f.write('X'); System.out.println(f.toString()); |
The PrintStream class provides output capabilities that we have beening using fom the System handle, System.out
PrintStream examples | System.out.println("Here are some numeric values in different formats.\n"); System.out.printf("Various integer formats: "); System.out.printf("%d %(d %+d %05d\n", 3, -3, 3, 3); System.out.println(); System.out.printf("Default floating-point format: %f\n", 1234567.123); System.out.printf("Floating-point with commas: %,f\n", 1234567.123); System.out.printf("Negative floating-point default: %,f\n", -1234567.123); System.out.printf("Negative floating-point option: %,(f\n", -1234567.123); System.out.println(); System.out.printf("Line up positive and negative values:\n"); System.out.printf("% ,.2f\n% ,.2f\n", 1234567.123, -1234567.123); |
DataOutputStream and DataInputStream Classes
The DataOutputStream and DataInputStream classes allow you to write/read primitive data to or from a stream. They implement eh dataOutput and DataInput interfaces which defines methods that converts primitive values to or from a sequence of bytes, they are idea to store binary data in files.
DataOutputStream and DataInputStream example | // First, write the data. try ( DataOutputStream dout = new DataOutputStream(new FileOutputStream("Test.dat")) ) { dout.writeDouble(98.6); dout.writeInt(1000); dout.writeBoolean(true); } catch(FileNotFoundException e) { System.out.println("Cannot Open Output File"); return; } catch(IOException e) { System.out.println("I/O Error: " + e); } // Now, read the data back. try ( DataInputStream din = new DataInputStream(new FileInputStream("Test.dat")) ) { double d = din.readDouble(); int i = din.readInt(); boolean b = din.readBoolean(); System.out.println("Here are the values: " + d + " " + i + " " + b); } catch(FileNotFoundException e) { System.out.println("Cannot Open Input File"); return; } catch(IOException e) { System.out.println("I/O Error: " + e); } |
The RandomAccessFile uses DataInput and Dataoutput interfaces, is special becuase it supports positioning in a file, basically you move a pointer through the file.
RandomAccessFile examples | // Reading RandomAccessFile raf = new RandomAccessFile("file.txt", "r"); raf.seek(1); byte[] bytes = new byte[5]; raf.read(bytes); raf.close(); System.out.println(new String(bytes)); // Writing RandomAccessFile raf = new RandomAccessFile("file.txt", "rw"); raf.seek(5); raf.write("Data".getBytes()); raf.close(); |
Character Streams are used when you need Unicode characters, at the top of the hierarchies are the Reader and Writer abstract classes.
FileReader examples | try ( FileReader fr = new FileReader("FileReaderDemo.java") ) { int c; // Read and display the file. while((c = fr.read()) != -1) System.out.print((char) c); } catch(IOException e) { System.out.println("I/O Error: " + e); } |
FileWriter examples | String source = "Now is the time for all good men\n to come to the aid of their country\n and pay their due taxes."; char buffer[] = new char[source.length()]; source.getChars(0, source.length(), buffer, 0); try ( FileWriter f0 = new FileWriter("file1.txt"); FileWriter f1 = new FileWriter("file2.txt"); FileWriter f2 = new FileWriter("file3.txt") ) { // write to first file for (int i=0; i < buffer.length; i += 2) { f0.write(buffer[i]); } // write to second file f1.write(buffer); // write to third file f2.write(buffer,buffer.length-buffer.length/4,buffer.length/4); } catch(IOException e) { System.out.println("An I/O Error Occured"); } |
CharArrayReader | String tmp = "abcdefghijklmnopqrstuvwxyz"; int length = tmp.length(); char c[] = new char[length]; tmp.getChars(0, length, c, 0); int i; try (CharArrayReader input1 = new CharArrayReader(c) ) { System.out.println("input1 is:"); while((i = input1.read()) != -1) { System.out.print((char)i); } System.out.println(); } catch(IOException e) { System.out.println("I/O Error: " + e); } try ( CharArrayReader input2 = new CharArrayReader(c, 0, 5) ) { System.out.println("input2 is:"); while((i = input2.read()) != -1) { System.out.print((char)i); } System.out.println(); } catch(IOException e) { System.out.println("I/O Error: " + e); } |
CharArrayWriter | CharArrayWriter f = new CharArrayWriter(); String s = "This should end up in the array"; char buf[] = new char[s.length()]; s.getChars(0, s.length(), buf, 0); try { f.write(buf); } catch(IOException e) { System.out.println("Error Writing to Buffer"); return; } System.out.println("Buffer as a string"); System.out.println(f.toString()); System.out.println("Into array"); char c[] = f.toCharArray(); for (int i=0; i < c.length; i++) { System.out.print(c[i]); } System.out.println("\nTo a FileWriter()"); // Use try-with-resources to manage the file stream. try ( FileWriter f2 = new FileWriter("test.txt") ) { f.writeTo(f2); } catch(IOException e) { System.out.println("I/O Error: " + e); } System.out.println("Doing a reset"); f.reset(); for (int i=0; i < 3; i++) f.write('X'); System.out.println(f.toString()); |
BufferedReader/BufferedWriter Example | File file = new File("file.txt"); // Writing file using BufferedWriter FileWriter fileWriter = null; BufferedWriter bufferedWriter = null; try ( BufferedWriter bw = new BufferedWriter(new FileWriter(file)) ) { bw.write("This is an example \n"); bw.write("of using BufferedWriter and \n"); bw.write("BufferedReader."); bw.flush(); } catch (IOException e) { e.printStackTrace(); } // Reading file using BufferedReader*/ try ( BufferedReader br = new BufferedReader(new FileReader(file)) ) { String line = null; while((line = br.readLine()) != null){ System.out.println(line); } } catch (IOException e) { e.printStackTrace(); } |
The Console Class provides basic input and output support for applications that read from and write characters to the console.
Console example | String str; Console con; // Obtain a reference to the console. con = System.console(); // If no console available, exit. if(con == null) return; // Read a string and then display it. str = con.readLine("Enter a string: "); con.printf("Here is your string: %s\n", str); |
Serialization is the process of writing the state of an object to a byte stream, this is usefull for storing application data to a file (persistant), the process to restore the data is called deserialization, serialized objects can then be passed over the network. The Externalizable interface can be used to compress or encrypt objects.
ObjectOutputStream and ObjectInputStream extends InputStream/OutputStream classes and implement the ObjectOutput/ObjectInput interfaces, these two classes fully support serialization, both have a number of methods with writing and reading serializied objects.
Serialization example | // Object to serialize class MyClass implements Serializable { String s; int i; double d; public MyClass(String s, int i, double d) { this.s = s; this.i = i; this.d = d; } public String toString() { return "s=" + s + "; i=" + i + "; d=" + d; } } Main -------------------------------------- // Object serialization try ( ObjectOutputStream objOutStream = new ObjectOutputStream(new FileOutputStream("serial")) ) { MyClass object1 = new MyClass("Hello", -7, 2.7e10); System.out.println("object1: " + object1); objOutStream.writeObject(object1); } catch(IOException e) { System.out.println("Exception during serialization: " + e); } // Object deserialization try ( ObjectInputStream objInStream = new ObjectInputStream(new FileInputStream("serial")) ) { MyClass object2 = (MyClass) objInStream.readObject(); // Cast to MyClass as its type Object System.out.println("object2: " + object2); } catch(Exception e) { System.out.println("Exception during deserialization: " + e); } Output ---------------------------- object1: s=Hello; i=-7; d=2.7E10 object2: s=Hello; i=-7; d=2.7E10 |