Java Programming: The IO Package
Java Programming: The IO Package
CHAPTER 20
The IO Package
Contents
Streams Overview Byte Streams Character Streams InputStreamReader and OutputStreamWriter The Data Byte Streams Working with Files Object Serialization The IOException Classes A Taste of New I/O
2
The java.io package defines I/O in terms of streams. The Java.nio package and its subpackages define I/O in terms of buffers and channels. Here the nio is acronym of new I/O. The java.net package provides specific support for network I/O, based around the use of sockets, with an underlying stream or channel-based model.
3
Streams Overview
Two Major parts in the package java.io : character(16-bit UTF-16 characters) streams and byte(8 bits) streams I/O is either text-based or data-based (binary) Input streams or output streams byte stream Readers or Writers character streams Five group of classes and interfaces in java.io
The general classes for building different types of byte and character streams. A range of classes that define various types of streams filtered, piped, and some specific instances of streams The data stream classes and interfaces for reading and writing primitive values and strings. For Interacting with files For the object serialization mechanism
4
FileInputStrea m FilterInputStream
BufferedInputStre am DataInputStream
Object FileOutputStrea m
OutputStrea m
BufferedOutputStrea m
FilterOutputStre am
DataOutputStream PrintStream
Byte Streams
AutioInputStream FileInputStream ObjectInputStrea m SequenceInputStrea m ByteArrayInputStrea m PipedInputStream FilterInputStream
6
InputStream
Byte Streams
FileOutputStream ObjectOutputStre am OutputStrea m ByteArrayOutputStre am PipeOutputStrea m FilterOutputStrea m
Byte Streams
import java.io.*; public class CountBytes { public static void main(String[] args) throws IOException { InputStream in; if (args.length == 0) in = System.in; else in = new FileInputStream(args[0]); int total = 0; while (in.read() != -1) total++; System.out.println(total + " bytes"); } }
8
The abstract class InputStream declares methods to read bytes from a particular source.
Type is InputStream
Reads a single byte of data and returns the byte that was read, as an integer in the range 0 to 255, not -128 to 127(unsigned).
Byte Streams
import java.io.*;
The abstract class OutputStream provides an abstraction for writing bytes to a destination.
public class TranslateByte { public static void main(String[] args) throws IOException { byte from = (byte) args[0].charAt(0); byte to = (byte) args[1].charAt(0); int b; while ((b = System.in.read()) != -1) System.out.write(b == from ? to : b); } } Run:
Type is PrintStream
Character Streams
Reade r Object BufferedRead er InputStreamRead er
FileReade r
10
Character Streams
BufferedReader InputStreamRead er Reade r StringReader CharArrayReader PipedReader FilterReader
11
Character Streams
BufferedWriter OutputStreamWri ter Writer StringWriter CharArrayWriter PipedWriter FilterWriter PrintWriter
12
Character Streams
import java.io.*; public class CountSpace { public static void main(String[] args) throws IOException { Reader in; if (args.length == 0) in = new InputStreamReader(System.in); else in = new FileReader(args[0]);
The abstract classes for reading and writing streams of characters are Reader and Writer. The abstract class Reader provides a character stream analogous to the byte stream InputStream and the methods of Reader essentially mirror those of InputStream. Run: Java CountSpace CountSpace.java Result: 520 characters 172 spaces
int ch; int total; int spaces = 0; for (total = 0; (ch = in.read()) != -1; total++) { if (Character.isWhitespace((char) ch)) spaces++; The conversion streams InputStreamReader } and OutputStreamWriter translate between System.out.println(total + " chars " character and byte streams using either a + spaces + " spaces"); } }
specified character set encoding or the default encoding for the local system.
13
Character Streams
The conversion streams InputStreamReader and OutputStreamWriter translate between character and byte streams using either a specified character set encoding or the default encoding for the local system.
public Reader readArabic(String file) throws IOException { InputStream fileIn = new FileInputStream(file); return new InputStreamReader(fileIn, "iso-88596"); }
The Stream types usually have input/output pairs, and most have both byte stream and character stream variants Filter streams Buffered streams Piped streams
Filter Streams
import java.io.*; abstract class public class UppercaseConvertor extends FilterReader { public UppercaseConvertor(Reader in) { super(in); } public int read() throws IOException { int c = super.read(); return (c==-1 ? c : Character.toUpperCase((char)c)); } public int read(char[] buf, int offset, int count) throws IOException { int nread = super.read(buf, offset, count); int last = offset + nread; for (int i = offset; i < last; i++) buf[i] = Character.toUpperCase(buf[i]); return nread; } public static void main(String[] args) throws IOException { StringReader src = new StringReader(args[0]); FilterReader f = new UppercaseConvertor(src); int c; while ( (c=f.read()) != -1) System.out.print((char)c); System.out.println(); } }
Function of the read() method was changed with filtering.
Filter streams help to chain streams to produce composite streams of greater utility. They get their power from the ability to filterprocess-what they read or write, transforming the data in some way. Run: % java UpperCaseConvertor no lowercase Result: NO LOWERCASE
15
Character Stream
abcdefghijklmnopqrstuvwxyz
16
The Print streams provide methods that make it easy to write the values of primitive types and object to a stream, in a human-readable text format print and println method The call out.print(f) is equivalent to out.write(String.valueOf(f).getBytes()); LineNumberReader The LineNumberReader stream keeps track of line numbers while reading text.
import java.io.*; public class FindChar { public static void main(String[] args) throws IOException { if (args.length != 2) throw new IllegalArgumentException( "need char and file"); int match = args[0].charAt(0); FileReader fileIn = new FileReader(args[1]); LineNumberReader in = new LineNumberReader(fileIn); int ch; while ((ch = in.read()) != -1) { if (ch == match) { System.out.println("'" + (char) ch + "' at line " + in.getLineNumber()); return ; } } System.out.println((char) match + " not found"); } }
17
Pushback Streams
A Pushback stream lets you push back, or unread characters or bytes when you have read too far. Pushback is typically useful for breaking input into tokens. For example, lexical scanners often know that a token (such as an identifier) has ended only when they have read the first character that follows it.
import java.io.*; public class SequenceCount { public static void main(String[] args) throws IOException { PushbackInputStream in = new PushbackInputStream(System.in); int max = 0; // longest sequence found int maxB = -1; // the byte in that sequence int b; // current byte in input do { int cnt; int b1 = in.read(); for (cnt = 1; (b = in.read()) == b1; cnt++) continue; if (cnt > max) { max = cnt; // remember length maxB = b1; // remember which byte value } in.unread(b); // pushback start of ntext seq } while (b != -1); // until we hit end of input System.out.println(max + " byte of " + maxB); } }
18
StreamTokenzier
The StreamTokenizer gives simple tokenization. More general facility for scanning and converting input text is provided by the java.util.Scanner class. Four token type TT_WORD TT_NUMBER TT_EOL TT_EOF Result
1) The 1) price 1) is 1) $ 1) 23.45 1) . 2) Is 2) that 2) too 2) expensive 2) ? 3) ( 3) I 3) dont 3) think 3) so 3) . 3) )
Input (tokens.txt)
The price is $23.45. Is that too expensive? (I dont think so.)
Run:
java StreamTokenizerDemo tokens.txt
import java.io.*; class StreamTokenizerDemo { public static void main(String args[]) { try { FileReader fr = new FileReader(args[0]); BufferedReader br = new BufferedReader(fr); StreamTokenizer st = new StreamTokenizer(br); st.ordinaryChar('.'); st.wordChars('\'', '\''); while(st.nextToken() != StreamTokenizer.TT_EOF) { switch(st.ttype) { case StreamTokenizer.TT_WORD: System.out.println(st.lineno() + ") " + st.sval); break; case StreamTokenizer.TT_NUMBER: System.out.println(st.lineno() + ") " + st.nval); break; default: System.out.println(st.lineno() + ") " + (char)st.ttype); } } fr.close(); } catch (Exception e) { System.out.println("Exception: " + e); } } }
19
DataInput and DataOutput These interfaces define methods that transmit primitive types across a stream. Read / Write methods
Write writeBoolean writeChar writeByte writeShort writeInt writeLong writeFloat writeDouble writeUTF Type boolean char byte short int long float double String(in UTF
Read readBoolean readChar readByte readShort readInt readLong readFloat readDouble readUTF format)
public static void writeData(double[] data, String file) throws IOException { OutputStream fout = new FileOutputStream(file); DataOutputStream out = new DataOutputStream(fout); out.writeInt(data.length) for(double d : data) out.writeDouble(d); out.close(); } public static double[] readData(String file) throws IOException { InputStream fin = new FileInputStream(file); DataInputStream in = new DataInputStream(fin); double[] data = new double[in.readInt()]; for (int i = 0; i < data.length; i++) data[i] = in.readDouble(); in.close(); return data; }
20
File Streams and FileDescriptor File Streams allow you to read a file as a stream for input or output. A FileDescriptor object represents a system-dependent value that describes an open file. The RandomAccessFile class behaves like a large array of bytes stored in the file system using the file pointer. The File class provides methods to separate pathnames into subcomponents and to ask the file system about the file a path name refers to (You can refer to the other reference). FilenameFilter and FileFilter
import java.io.*; public class DirFilter implements FilenameFilter { public boolean accept(File dir, String name) { return new File(dir, name).isDirectory(); } public static void main(String[] args) { File dir = new File(args[0]); String[] files = dir.list(new DirFilter()); System.out.println(files.length + " dir(s):"); for (String file : files) System.out.println("\t" + file); } }
The FilenameFilter interface provides objects that filter unwanted files from a list.
21
Object Serialization
What
is Object Serialization?
Serialization:
process of converting an objects representation into a stream of bytes Deserialization: reconstituting an object from a byte stream Process of reading and writing objects Writing an object is to represent its state in a serialized form sufficient to reconstruct the object as it is read. Object serialization is essential to building all but the most transient applications.
22
Serializing Objects
Writing objects to a stream is a straightforward process. Example of constructing a Date object and then serializing that object:
Example that reads in the String and the Date object that was written to the file named theTime in the read example:
FileInputStream in = new FileInputStream("theTime"); ObjectInputStream s = new ObjectInputStream(in); String today = (String)s.readObject(); Date date = (Date)s.readObject();
Serializing Objects
Providing Object Serialization for Your Classes Implementing the Serializable Interface Customizing Serialization Implementing the Externalizable Interface Protecting Sensitive Information [ObjectFileTest.java]
/home/course/prog3/sources/week08-14/IO/objserial/ObjectFileTest.java
24
The new I/O (NIO) APIs introduced in v 1.4 provide new features and improved performance in the areas of buffer management, scalable network and file I/O, character-set support, and regularexpression matching. The NIO APIs supplement the I/O facilities in the java.io package.
Features
Buffers for data of primitive types Character-set encoders and decoders A pattern-matching facility based on Perl-style regular expressions Channels, a new primitive I/O abstraction A file interface that supports locks and memory mapping
25
The channel transfers data between the buffers and the file stream
Channel Object
Buffer Objects
26
Accessing Files
Channels
Channels were introduced in the 1.4 release of Java to provide a faster capability for a faster capability for input and output operations with files, network sockets, and piped I/O operations between programs than the methods provided by the stream classes. The channel mechanism can take advantage of buffering and other capabilities of the underlying operating system and therefore is considerably more efficient than using the operations provided directly within the file stream classes.
A File object encapsulates a path to a file or a directory, and such an object encapsulating a file path can be used to construct a file stream object. A FileInputStream object encapsulates a file that can be read by a channel. A FileoutputStream object encapsulates a file that can be written by a channel. A buffer just holds data in memory. The loaded data to be written to a file will be saved at buffer using the buffers put() method, and retrieved using buffers get() methods. A FileChannel object can be obtained from a file stream object or a RandomAccessFile object.
27
Accessing Files
The hierarchy of the channel interfaces
28
Accessing Files
The Capacities of Different Buffers
29
public class ReadPrimes { public static void main(String[] args) { File aFile = new File("primes.bin"); From the FileInputStream inFile = null; channel, read try { data and save inFile = new FileInputStream(aFile); to the buffer } catch(FileNotFoundException e) { e.printStackTrace(System.err); System.exit(1); Channel Setup } FileChannel inChannel = inFile.getChannel(); final int PRIMECOUNT = 6; ByteBuffer buf = ByteBuffer.allocate(8*PRIMECOUNT); long[] primes = new long[PRIMECOUNT]; Buffer Setup