chapter 12: java io system ● io library design is challenging – many input and output devices...

Post on 01-Apr-2015

220 Views

Category:

Documents

1 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Chapter 12: JAVA IO System

● IO library design is challenging– Many input and output devices (console, file, network,

etc.)– Many formats (binary, character, by lines, by words,

etc.)– Many ways (sequential, random access, buffered)

● JAVA provides a lot of classes for IO

File class

● To abstract access to files on disk, JAVA provides a File class

● A File object can refer to a single file on disk or to a list of files on disk (a directory listing)

File class example public static void main(String[] args) { File path = new File("."); String[] list; if(args.length == 0) list = path.list(); else list = path.list(new DirFilter(args[0])); Arrays.sort(list, new AlphabeticComparator()); for(int i = 0; i < list.length; i++) System.out.println(list[i]); }}

class DirFilter implements FilenameFilter { private Pattern pattern; public DirFilter(String regex) { pattern = Pattern.compile(regex); } public boolean accept(File dir, String name) { // Strip path information, search for regex: return pattern.matcher( new File(name).getName()).matches(); }} ///:~

Some other File class methodspublic class MakeDirectories { private static Test monitor = new Test(); private static void usage() { System.err.println( "Usage:MakeDirectories path1 ...\n" + "Creates each path\n" + "Usage:MakeDirectories -d path1 ...\n" + "Deletes each path\n" + "Usage:MakeDirectories -r path1 path2\n" + "Renames from path1 to path2"); System.exit(1); } private static void fileData(File f) { System.out.println( "Absolute path: " + f.getAbsolutePath() + "\n Can read: " + f.canRead() + "\n Can write: " + f.canWrite() + "\n getName: " + f.getName() + "\n getParent: " + f.getParent() + "\n getPath: " + f.getPath() + "\n length: " + f.length() + "\n lastModified: " + f.lastModified()); if(f.isFile()) System.out.println("It's a file"); else if(f.isDirectory()) System.out.println("It's a directory"); }

Some other File class methods (cont.)

public static void main(String[] args) { if(args.length < 1) usage(); if(args[0].equals("-r")) { if(args.length != 3) usage(); File old = new File(args[1]), rname = new File(args[2]); old.renameTo(rname); fileData(old); fileData(rname); return; // Exit main } int count = 0; boolean del = false; if(args[0].equals("-d")) { count++; del = true; } count--;

Some other File class methods (cont.) while(++count < args.length) { File f = new File(args[count]); if(f.exists()) { System.out.println(f + " exists"); if(del) { System.out.println("deleting..." + f); f.delete(); } } else { // Doesn't exist if(!del) { f.mkdirs(); System.out.println("created " + f); } } fileData(f); } if(args.length == 1 && args[0].equals("MakeDirectoriesTest")) }}

JAVA IO Library

●InputStream and Reader are top classes in Java IO hierarchy. They provide read method that can be use to read a single bye or array of bytes

●OutputStream and Writer are top classes in Java IO hierarchy. They provide write method to write a single bye or an array of bytes

●Other lower classes provides more usefull functionality than those povided by these top classes

●So in programming normally we use lower classes

Types of InputStream

Types of InputStream (cont.)

Types of OutputStream

Uses of FilterInputStream and FilterOutputStream

● Basic IO classes in JAVA provides very primitive functionality which is not very useful. For example to read a String we need to read a series of bytes (into an array) and then convert them to a single String.

● To provide higher level functionality, Java uses decorator design pattern and uses Filter classes.

● Decorator design pattern provides a way to add functionlaity to classes in a transparant way. So if we have an InputStream then a FilterInputStream adds some (usefull) functionality to it without affecting its basic functionality

Reading from an InputStream with FilterInputStream

Reading from an InputStream with FilterInputStream (cont.)

Writing to an OutputStream with FilterOutputStream

Readers and Writers

● Reader and Writer classes were added in Java 1.1

● They provide character oriented I/O (Streams provides byte oriented I/O)

● They are unicode compliant which is necessary for internationalization

● In programs it is a good practice to first try to user Reader and Writer classes instead of Stream classes

● However in some situation you must use Stream classes (like processing a zip file)

Correspondence of Streams and Reader/Writer classes

Corresponding filters

Typical I/O uses

// 1. Reading input by lines: BufferedReader in = new BufferedReader( new FileReader("IOStreamDemo.java"));String s, s2 = new String(); while((s = in.readLine())!= null) s2 += s + "\n";in.close();

Typical I/O uses (cont.)

// 1b. Reading standard input: BufferedReader stdin = new BufferedReader( new InputStreamReader(System.in)); System.out.print("Enter a line:"); System.out.println(stdin.readLine());

Typical I/O uses (cont.)

// 2. Input from memoryStringReader in2 = new StringReader(s2); int c; while((c = in2.read()) != -1) System.out.print((char)c);

Typical I/O uses (cont.)

// 3. Formatted memory input try { DataInputStream in3 = new DataInputStream( new ByteArrayInputStream(s2.getBytes())); while(true) System.out.print((char)in3.readByte()); } catch(EOFException e) { System.err.println("End of stream"); }

Typical I/O uses (cont.)

// 4. File output try { BufferedReader in4 = new BufferedReader( new StringReader(s2)); PrintWriter out1 = new PrintWriter( new BufferedWriter(new FileWriter("IODemo.out"))); int lineCount = 1; while((s = in4.readLine()) != null ) out1.println(lineCount++ + ": " + s); out1.close(); } catch(EOFException e) { System.err.println("End of stream"); }

Typical I/O uses (cont.) // 5. Storing & recovering data try { DataOutputStream out2 = new DataOutputStream( new BufferedOutputStream( new FileOutputStream("Data.txt"))); out2.writeDouble(3.14159); out2.writeUTF("That was pi"); out2.writeDouble(1.41413); out2.writeUTF("Square root of 2"); out2.close(); DataInputStream in5 = new DataInputStream( new BufferedInputStream( new FileInputStream("Data.txt"))); // Must use DataInputStream for data: System.out.println(in5.readDouble()); // Only readUTF() will recover the // Java-UTF String properly: System.out.println(in5.readUTF()); // Read the following double and String: System.out.println(in5.readDouble()); System.out.println(in5.readUTF()); } catch(EOFException e) { throw new RuntimeException(e); }

Typical I/O uses (cont.)

// 6. Reading/writing random access files RandomAccessFile rf = new RandomAccessFile("rtest.dat", "rw"); for(int i = 0; i < 10; i++) rf.writeDouble(i*1.414); rf.close(); rf = new RandomAccessFile("rtest.dat", "rw"); rf.seek(5*8); rf.writeDouble(47.0001); rf.close(); rf = new RandomAccessFile("rtest.dat", "r"); for(int i = 0; i < 10; i++) System.out.println("Value " + i + ": " + rf.readDouble()); rf.close();}

Making a file handling utilitypackage com.bruceeckel.util;import java.io.*;import java.util.*;

public class TextFile extends ArrayList { // Tools to read and write files as single strings: public static String read(String fileName) throws IOException { StringBuffer sb = new StringBuffer(); BufferedReader in = new BufferedReader(new FileReader(fileName)); String s; while((s = in.readLine()) != null) { sb.append(s); sb.append("\n"); } in.close(); return sb.toString(); } public static void write(String fileName, String text) throws IOException { PrintWriter out = new PrintWriter( new BufferedWriter(new FileWriter(fileName))); out.print(text); out.close(); }

Making a file handling utility (cont.)

public TextFile(String fileName) throws IOException { super(Arrays.asList(read(fileName).split("\n"))); }

public void write(String fileName) throws IOException { PrintWriter out = new PrintWriter( new BufferedWriter(new FileWriter(fileName))); for(int i = 0; i < size(); i++) out.println(get(i)); out.close(); }

// Simple test: public static void main(String[] args) throws Exception { String file = read("TextFile.java"); write("test.txt", file); TextFile text = new TextFile("test.txt"); text.write("test2.txt"); }}

Reading from standard input

import java.io.*;

public class Echo { public static void main(String[] args) throws IOException { BufferedReader in = new BufferedReader( new InputStreamReader(System.in)); String s; while((s = in.readLine()) != null && s.length() != 0) System.out.println(s); // An empty line or Ctrl-Z terminates the program }}

Redirecting standard I/Opublic class Redirecting { // Throw exceptions to console: public static void main(String[] args) throws IOException { PrintStream console = System.out; BufferedInputStream in = new BufferedInputStream( new FileInputStream("Redirecting.java")); PrintStream out = new PrintStream( new BufferedOutputStream( new FileOutputStream("test.out"))); System.setIn(in); System.setOut(out); System.setErr(out); BufferedReader br = new BufferedReader( new InputStreamReader(System.in)); String s; while((s = br.readLine()) != null) System.out.println(s); out.close(); // Remember this! System.setOut(console); }}

JAVA new IO - nio

● Introduced in JDK 1.4 in java.nio.* packages● The main goal is speed of I/O operation● It does it by providing I/O facilities that are more near the way operating systesm does I/O operations● It does it by introducing channels and buffers● FileInputStream, FileOutputStream and RandomAccessFile from old java IO library have been modified to produce a FileChannel

Java neo IO - exampleimport java.nio.channels.*;public class GetChannel { private static final int BSIZE = 1024; public static void main(String[] args) throws Exception { // Write a file: FileChannel fc = new FileOutputStream("data.txt").getChannel(); fc.write(ByteBuffer.wrap("Some text ".getBytes())); fc.close(); // Add to the end of the file: fc = new RandomAccessFile("data.txt", "rw").getChannel(); fc.position(fc.size()); // Move to the end fc.write(ByteBuffer.wrap("Some more".getBytes())); fc.close(); // Read the file: fc = new FileInputStream("data.txt").getChannel(); ByteBuffer buff = ByteBuffer.allocate(BSIZE); fc.read(buff); buff.flip(); while(buff.hasRemaining()) System.out.print((char)buff.get()); }}

File copy using channels

public class ChannelCopy { private static final int BSIZE = 1024; public static void main(String[] args) throws Exception { if(args.length != 2) { System.out.println("arguments: sourcefile destfile"); System.exit(1); } FileChannel in = new FileInputStream(args[0]).getChannel(), out = new FileOutputStream(args[1]).getChannel(); ByteBuffer buffer = ByteBuffer.allocate(BSIZE); while(in.read(buffer) != -1) { buffer.flip(); // Prepare for writing out.write(buffer); buffer.clear(); // Prepare for reading } }}

Better way for file copy using transferTo()

public class TransferTo { public static void main(String[] args) throws Exception { if(args.length != 2) { System.out.println("arguments: sourcefile destfile"); System.exit(1); } FileChannel in = new FileInputStream(args[0]).getChannel(), out = new FileOutputStream(args[1]).getChannel(); in.transferTo(0, in.size(), out); // Or: // out.transferFrom(in, 0, in.size()); }}

View bufferspublic class IntBufferDemo { private static Test monitor = new Test(); private static final int BSIZE = 1024; public static void main(String[] args) { ByteBuffer bb = ByteBuffer.allocate(BSIZE); IntBuffer ib = bb.asIntBuffer(); // Store an array of int: ib.put(new int[] { 11, 42, 47, 99, 143, 811, 1016 }); // Absolute location read and write: System.out.println(ib.get(3)); ib.put(3, 1811); ib.rewind(); while(ib.hasRemaining()) { int i = ib.get(); if(i == 0) break; // Else we'll get the entire buffer System.out.println(i); } monitor.expect(new String[] { "99", "11", "42", "47", "1811", "143", "811", "1016" }); }} ///:~

Endians

public class Endians { private static Test monitor = new Test(); public static void main(String[] args) { ByteBuffer bb = ByteBuffer.wrap(new byte[12]); bb.asCharBuffer().put("abcdef"); System.out.println(Arrays2.toString(bb.array())); bb.rewind(); bb.order(ByteOrder.BIG_ENDIAN); bb.asCharBuffer().put("abcdef"); System.out.println(Arrays2.toString(bb.array())); bb.rewind(); bb.order(ByteOrder.LITTLE_ENDIAN); bb.asCharBuffer().put("abcdef"); System.out.println(Arrays2.toString(bb.array())); monitor.expect(new String[]{ "[0, 97, 0, 98, 0, 99, 0, 100, 0, 101, 0, 102]", "[0, 97, 0, 98, 0, 99, 0, 100, 0, 101, 0, 102]", "[97, 0, 98, 0, 99, 0, 100, 0, 101, 0, 102, 0]" }); } }

Buffer interface

Example of buffer functionalitypublic class UsingBuffers { private static Test monitor = new Test(); private static void symmetricScramble(CharBuffer buffer){ while(buffer.hasRemaining()) { buffer.mark(); char c1 = buffer.get(); char c2 = buffer.get(); buffer.reset(); buffer.put(c2).put(c1); } } public static void main(String[] args) { char[] data = "UsingBuffers".toCharArray(); ByteBuffer bb = ByteBuffer.allocate(data.length * 2); CharBuffer cb = bb.asCharBuffer(); cb.put(data); System.out.println(cb.rewind()); symmetricScramble(cb); System.out.println(cb.rewind()); symmetricScramble(cb); System.out.println(cb.rewind()); monitor.expect(new String[] { "UsingBuffers", "sUniBgfuefsr", "UsingBuffers" }); }}

Memory mapped files

public class LargeMappedFiles { static int length = 0x8FFFFFF; // 128 Mb public static void main(String[] args) throws Exception { MappedByteBuffer out = new RandomAccessFile("test.dat", "rw").getChannel() .map(FileChannel.MapMode.READ_WRITE, 0, length); for(int i = 0; i < length; i++) out.put((byte)'x'); System.out.println("Finished writing"); for(int i = length/2; i < length/2 + 6; i++) System.out.print((char)out.get(i)); }}

Performance test

● In the book, ther is a test program that demonstrates that memory mapped files show better performance

Stream Write: 1719Mapped Write: 359Stream Read: 750Mapped Read: 125Stream Read/Write: 5188Mapped Read/Write: 16

File locking

public class FileLocking { public static void main(String[] args) throws Exception { FileOutputStream fos= new FileOutputStream("file.txt"); FileLock fl = fos.getChannel().tryLock(); if(fl != null) { System.out.println("Locked File"); Thread.sleep(100); fl.release(); System.out.println("Released Lock"); } fos.close(); }}

Compression related classes

Simple compression with GZIP

BufferedReader in = new BufferedReader( new FileReader(args[0])); BufferedOutputStream out = new BufferedOutputStream( new GZIPOutputStream( new FileOutputStream("test.gz"))); System.out.println("Writing file"); int c; while((c = in.read()) != -1) out.write(c); in.close(); out.close(); System.out.println("Reading file"); BufferedReader in2 = new BufferedReader( new InputStreamReader(new GZIPInputStream( new FileInputStream("test.gz")))); String s; while((s = in2.readLine()) != null) System.out.println(s);

JAR (Java Archieve) files

jar files are zip files with .jar suffix● We use them to compress and group a number of classes into a single file● This is a convenient way for libraries and transfering applets over internet● With the jar utility you can make a jar file

jar [options] destination [manifest] inputfile(s)

Object serialization

● Using Object Serialization we can store an image of an object to a file or transfer it through a network connection● This is a mechanism we need to do Remote Method Invocation (RMI)● Also it is helpful to persist some objects and use them later● For an object to be serialized, the object should implement Serializable interface● ObjectOutputStream and ObjectInputStream can be used to serialize and de-serialize objects

Object serialization code fragment

public class Worm implements Serializable {

// body of the class

}

// ....

ObjectOutputStream out = new ObjectOutputStream( new FileOutputStream("worm.out")); out.writeObject("Worm storage\n");

out.writeObject(w);

out.close(); // Also flushes output

ObjectInputStream in = new ObjectInputStream( new FileInputStream("worm.out"));

String s = (String)in.readObject();

Worm w2 = (Worm)in.readObject();

Contolling object serialization

Serializabe interface is good when we want to serialize full object (a web of objects which are included in the serialized object)To control which members are serialized, we can use Externalizable interface (see samples in the book)Also we can use transient keyword for data members that we don't want serialized (see sample in the book):

public class Logon implements Serializable { private Date date = new Date(); private String username; private transient String password; // rest of the class

Regular expressions

● Regualr expressions are powerful and flexible text processing tools● Using pattern matching with regular expressions we can find complex patterns in Strings● We have seen the usage of regular expressions inside expect method calls

Regular expression constructs (not complete)

Regular expression constructs (not complete) (cont.)

Pattern and Matcher

public class TestRegularExpression { public static void main(String[] args) { if(args.length < 2) { System.out.println("Usage:\n" + "java TestRegularExpression " + "characterSequence regularExpression+"); System.exit(0); } System.out.println("Input: \"" + args[0] + "\""); for(int i = 1; i < args.length; i++) { System.out.println( "Regular expression: \"" + args[i] + "\""); Pattern p = Pattern.compile(args[i]); Matcher m = p.matcher(args[0]); while(m.find()) { System.out.println("Match \"" + m.group() + "\" at positions " + m.start() + "-" + (m.end() - 1)); } } }}

Groupspublic class Groups { private static Test monitor = new Test(); static public final String poem = "Twas brillig, and the slithy toves\n" + "Did gyre and gimble in the wabe.\n" + "All mimsy were the borogoves,\n" + "And the mome raths outgrabe.\n\n" + "Beware the Jabberwock, my son,\n" + "The jaws that bite, the claws that catch.\n" + "Beware the Jubjub bird, and shun\n" + "The frumious Bandersnatch."; public static void main(String[] args) { Matcher m = Pattern.compile("(?m)(\\S+)\\s+((\\S+)\\s+(\\S+))$") .matcher(poem); while(m.find()) { for(int j = 0; j <= m.groupCount(); j++) System.out.print("[" + m.group(j) + "]"); System.out.println(); }

Groups (cont.)

monitor.expect(new String[]{ "[the slithy toves]" + "[the][slithy toves][slithy][toves]", "[in the wabe.][in][the wabe.][the][wabe.]", "[were the borogoves,]" + "[were][the borogoves,][the][borogoves,]", "[mome raths outgrabe.]" + "[mome][raths outgrabe.][raths][outgrabe.]", "[Jabberwock, my son,]" + "[Jabberwock,][my son,][my][son,]", "[claws that catch.]" + "[claws][that catch.][that][catch.]", "[bird, and shun][bird,][and shun][and][shun]", "[The frumious Bandersnatch.][The]" + "[frumious Bandersnatch.][frumious][Bandersnatch.]" }); }}

Split()

public class SplitDemo { private static Test monitor = new Test(); public static void main(String[] args) { String input = "This!!unusual use!!of exclamation!!points"; System.out.println(Arrays.asList( Pattern.compile("!!").split(input))); // Only do the first three: System.out.println(Arrays.asList( Pattern.compile("!!").split(input, 3))); System.out.println(Arrays.asList( "Aha! String has a split() built in!".split(" "))); monitor.expect(new String[] { "[This, unusual use, of exclamation, points]", "[This, unusual use, of exclamation!!points]", "[Aha!, String, has, a, split(), built, in!]" }); }}

top related