Download chapter12

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
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 methods
public 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 memory
StringReader 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 utility
package 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/O
public 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 - example
import 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 buffers
public 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 functionality
public 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: 1719
Mapped Write: 359
Stream Read: 750
Mapped Read: 125
Stream Read/Write: 5188
Mapped 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));
}
}
}
}
Groups
public 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!]"
});
}
}