Java IO系统
“对语言设计人员来说,创建好的输入/输出系统是一项特别困难的任务。”
由于存在大量不同的设计方案,所以该任务的困难性是很容易证明的。其中最大的挑战似乎是如何覆盖所有可能的因素。不仅有三种不同的种类的IO需要考虑(文件、控制台、网络连接),而且需要通过大量不同的方式与它们通信(顺序、随机访问、二进制、字符、按行、按字等等)。
Java库的设计者通过创建大量类来攻克这个难题。事实上,Java的IO系统采用了如此多的类,以致刚开始会产生不知从何处入手的感觉(具有讽刺意味的是,Java的IO设计初衷实际要求避免过多的类)。从Java 1.0升级到Java 1.1后,IO库的设计也发生了显著的变化。此时并非简单地用新库替换旧库,Sun的设计人员对原来的库进行了大手笔的扩展,添加了大量新的内容。因此,我们有时不得不混合使用新库与旧库,产生令人无奈的复杂代码。
本章将帮助大家理解标准Java库内的各种IO类,并学习如何使用它们。本章的第一部分将介绍“旧”的Java 1.0 IO流库,因为现在有大量代码仍在使用那个库。本章剩下的部分将为大家引入Java 1.1 IO库的一些新特性。注意若用Java 1.1编译器来编译本章第一部分介绍的部分代码,可能会得到一条“不建议使用该特性”(Deprecated feature)警告消息。代码仍然能够使用;编译器只是建议我们换用本章后面要讲述的一些新特性。但我们这样做是有价值的,因为可以更清楚地认识老方法与新方法之间的一些差异,从而加深我们的理解(并可顺利阅读为Java 1.0写的代码)。
10.1 输入和输出
可将Java库的IO类分割为输入与输出两个部分,这一点在用Web浏览器阅读联机Java类文档时便可知道。通过继承,从InputStream(输入流)衍生的所有类都拥有名为read()的基本方法,用于读取单个字节或者字节数组。类似地,从OutputStream衍生的所有类都拥有基本方法write(),用于写入单个字节或者字节数组。然而,我们通常不会用到这些方法;它们之所以存在,是因为更复杂的类可以利用它们,以便提供一个更有用的接口。因此,我们很少用单个类创建自己的系统对象。一般情况下,我们都是将多个对象重叠在一起,提供自己期望的功能。我们之所以感到Java的流库(Stream Library)异常复杂,正是由于为了创建单独一个结果流,却需要创建多个对象的缘故。
很有必要按照功能对类进行分类。库的设计者首先决定与输入有关的所有类都从InputStream继承,而与输出有关的所有类都从OutputStream继承。
10.1.1 InputStream的类型
InputStream的作用是标志那些从不同起源地产生输入的类。这些起源地包括(每个都有一个相关的InputStream子类):
(1) 字节数组
(2) String对象
(3) 文件
(4) “管道”,它的工作原理与现实生活中的管道类似:将一些东西置入一端,它们在另一端出来。 (5) 一系列其他流,以便我们将其统一收集到单独一个流内。
(6) 其他起源地,如Internet连接等(将在本书后面的部分讲述)。
除此以外,FilterInputStream也属于InputStream的一种类型,用它可为“破坏器”类提供一个基础类,以便将属性或者有用的接口同输入流连接到一起。这将在以后讨论。
Class
Function
Constructor Arguments
How to use it
ByteArray-InputStream |
Allows a buffer in memory to be used as anInputStream. |
The buffer from which to extract the bytes. |
As a source of data. Connect it to aFilterInputStream object to provide a useful interface. |
||
StringBuffer-InputStream |
Converts a String into anInputStream. |
A String. The underlying implementation actually uses aStringBuffer. |
As a source of data. Connect it to aFilterInputStream object to provide a useful interface. |
||
File-InputStream |
For reading information from a file. |
A String representing the file name, or a File or FileDescriptorobject. |
As a source of data. Connect it to aFilterInputStream object to provide a useful interface. |
Piped-InputStream |
Produces the data that’s being written to the associated PipedOutput-Stream. Implements the “piping” concept. |
PipedOutputStream |
As a source of data in multithreading. Connect it to aFilterInputStream object to provide a useful interface. |
||
Sequence-InputStream |
Coverts two or more InputStream objects into a single InputStream. |
Two InputStream objects or an Enumeration for a container of InputStreamobjects. |
As a source of data. Connect it to aFilterInputStream object to provide a useful interface. |
||
Filter-InputStream |
Abstract class which is an interface for decorators that provide useful functionality to the other InputStream classes. See Table 10-3. |
See Table 10-3. |
See Table 10-3. |
Class
Function
Constructor Arguments
How to use it
ByteArray-OutputStream |
Creates a buffer in memory. All the data that you send to the stream is placed in this buffer. |
Optional initial size of the buffer. |
To designate the destination of your data. Connect it to a FilterOutputStreamobject to provide a useful interface. |
||
File-OutputStream |
For sending information to a file. |
A String representing the file name, or a Fileor FileDescriptorobject. |
To designate the destination of your data. Connect it to a FilterOutputStreamobject to provide a useful interface. |
||
Piped-OutputStream |
Any information you write to this automatically ends up as input for the associated PipedInput-Stream.Implements the “piping” concept. |
PipedInputStream |
To designate the destination of your data for multithreading. Connect it to aFilterOutputStream object to provide a useful interface. |
||
Filter-OutputStream |
Abstract class which is an interface for decorators that provide useful functionality to the other OutputStream classes. See Table |
See Table 10-4. |
See Table 10-4. |
Class |
Function |
Constructor Arguments |
How to use it |
||
Data-InputStream |
Used in concert with DataOutputStream, so you can read primitives (int, char, long, etc.) from a stream in a portable fashion. |
InputStream |
Contains a full interface to allow you to read primitive types. |
Buffered-InputStream |
Use this to prevent a physical read every time you want more data. You’re saying “Use a buffer.” |
InputStream, with optional buffer size. |
This doesn’t provide an interface per se, just a requirement that a buffer be used. Attach an interface object. |
||
LineNumber-InputStream |
Keeps track of line numbers in the input stream; you can call getLineNumber( )and setLineNumber(int). |
InputStream |
This just adds line numbering, so you’ll probably attach an interface object. |
||
Pushback-InputStream |
Has a one byte push-back buffer so that you can push back the last character read. |
InputStream |
Generally used in the scanner for a compiler and probably included because the Java compiler needed it. You probably won’t use this. |
Class
Function
Constructor Arguments
How to use it
Data-OutputStream |
Used in concert with DataInputStream so you can write primitives (int, char, long, etc.) to a stream in a portable fashion. |
OutputStream |
Contains full interface to allow you to write primitive types. |
||
PrintStream |
For producing formatted output. WhileDataOutputStream handles the storage of data, PrintStream handles display. |
OutputStream, with optional boolean indicating that the buffer is flushed with every newline. |
Should be the “final” wrapping for your OutputStream object. You’ll probably use this a lot. |
||
Buffered-OutputStream |
Use this to prevent a physical write every time you send a piece of data. You’re saying “Use a buffer.” You can call flush( ) to flush the buffer. |
OutputStream, with optional buffer size. |
This doesn’t provide an interfaceper se, just a requirement that a buffer is used. Attach an interface object. |
//: DirList.java // Displays directory listing package c10; import java.io.*; publicclass DirList { public static void main(String[] args) { try { File path = newFile("."); String[] list; if(args.length == 0) list = path.list(); else list = path.list(newDirFilter(args[0])); for(int i = 0; i < list.length; i++) System.out.println(list[i]); }catch(Exception e) { e.printStackTrace(); } } } class DirFilter implementsFilenameFilter { String afn; DirFilter(String afn) { this.afn = afn; } public booleanaccept(File dir, String name) { // Strip path information: String f = newFile(name).getName(); return f.indexOf(afn) != -1; } } ///:~
//: DirList2.java // Uses Java 1.1 anonymous inner classes import java.io.*;public class DirList2 { public static FilenameFilter filter(final String afn) { // Creation of anonymous inner class: return new FilenameFilter() { String fn = afn; public boolean accept(File dir, String n) { // Strip path information: String f = new File(n).getName(); return f.indexOf(fn) != -1; } }; // End of anonymous inner class } public static void main(String[] args) { try { File path = newFile("."); String[] list; if(args.length == 0) list = path.list(); else list = path.list(filter(args[0])); for(int i = 0; i < list.length; i++) System.out.println(list[i]); } catch(Exception e) { e.printStackTrace(); } } } ///:~
//: DirList3.java // Building the anonymous inner class "in-place" importjava.io.*; public class DirList3 { public static void main(final String[] args) { try { File path = new File("."); String[] list; if(args.length == 0) list = path.list(); elselist = path.list( new FilenameFilter() { public boolean accept(File dir, String n) { String f = new File(n).getName(); return f.indexOf(args[0]) != -1; } }); for(int i = 0; i < list.length; i++) System.out.println(list[i]); } catch(Exception e) { e.printStackTrace(); } } } ///:~
//: SortedDirList.java // Displays sorted directory listing import java.io.*; importc08.*; public class SortedDirList { private File path; private String[] list; publicSortedDirList(final String afn) { path = new File("."); if(afn == null) list = path.list(); else list = path.list( new FilenameFilter() { public boolean accept(File dir, String n) { String f = new File(n).getName(); return f.indexOf(afn) != -1; } }); sort(); } void print() { for(int i = 0; i < list.length; i++) System.out.println(list[i]); }private void sort() { StrSortVector sv = new StrSortVector(); for(int i = 0; i < list.length; i++) sv.addElement(list[i]); // The first time an element is pulled from// the StrSortVector the list is sorted: for(int i = 0; i < list.length; i++) list[i] = sv.elementAt(i); } // Test it: public static void main(String[] args) { SortedDirList sd; if(args.length == 0) sd = new SortedDirList(null); else sd = newSortedDirList(args[0]); sd.print(); } } ///:~
//: MakeDirectories.java // Demonstrates the use of the File class to // create directories and manipulate files. import java.io.*; public class MakeDirectories {private final static String usage = "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/n"; private static void usage() { System.err.println(usage); 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"); } public static voidmain(String[] args) { if(args.length < 1) usage(); if(args[0].equals("-r")) {if(args.length != 3) usage(); File old = new File(args[1]), rname = newFile(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; } for( ; count < args.length; count++) { 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); } } } ///:~
//: IOStreamDemo.java // Typical IO Stream Configurations import java.io.*;import com.bruceeckel.tools.*; public class IOStreamDemo { public static voidmain(String[] args) { try { // 1. Buffered input file DataInputStream in = newDataInputStream( new BufferedInputStream( new FileInputStream(args[0]))); String s, s2 = new String(); while((s = in.readLine())!= null) s2 += s + "/n"; in.close(); // 2. Input from memory StringBufferInputStream in2 = newStringBufferInputStream(s2); int c; while((c = in2.read()) != -1) System.out.print((char)c); // 3. Formatted memory input try { DataInputStream in3 = new DataInputStream( new StringBufferInputStream(s2)); while(true) System.out.print((char)in3.readByte()); } catch(EOFException e) { System.out.println( "End of stream encountered"); } // 4. Line numbering & file output try { LineNumberInputStream li = new LineNumberInputStream( newStringBufferInputStream(s2)); DataInputStream in4 = new DataInputStream(li); PrintStream out1 = new PrintStream( new BufferedOutputStream( newFileOutputStream( "IODemo.out"))); while((s = in4.readLine()) != null ) out1.println( "Line " + li.getLineNumber() + s); out1.close(); // finalize() not reliable! } catch(EOFException e) { System.out.println( "End of stream encountered"); } // 5. Storing & recovering data try { DataOutputStream out2 =new DataOutputStream( new BufferedOutputStream( newFileOutputStream("Data.txt"))); out2.writeBytes( "Here's the value of pi: /n"); out2.writeDouble(3.14159); out2.close(); DataInputStream in5 = newDataInputStream( new BufferedInputStream( new FileInputStream("Data.txt"))); System.out.println(in5.readLine()); System.out.println(in5.readDouble()); }catch(EOFException e) { System.out.println( "End of stream encountered"); } // 6. Reading/writing random access files RandomAccessFile rf = newRandomAccessFile("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 = newRandomAccessFile("rtest.dat", "r"); for(int i = 0; i < 10; i++) System.out.println("Value " + i + ": " + rf.readDouble()); rf.close(); // 7. File input shorthand InFile in6 = new InFile(args[0]); String s3 = new String(); System.out.println( "First line in file: " + in6.readLine()); in6.close(); // 8. Formatted file output shorthandPrintFile out3 = new PrintFile("Data2.txt"); out3.print("Test of PrintFile"); out3.close(); // 9. Data file output shorthand OutFile out4 = newOutFile("Data3.txt"); out4.writeBytes("Test of outDataFile/n/r"); out4.writeChars("Test of outDataFile/n/r"); out4.close(); }catch(FileNotFoundException e) { System.out.println( "File Not Found:" + args[0]); } catch(IOException e) { System.out.println("IO Exception"); } } } ///:~
//: TestEOF.java // Testing for the end of file while reading // a byte at a time.import java.io.*; public class TestEOF { public static void main(String[] args) {try { DataInputStream in = new DataInputStream( new BufferedInputStream(new FileInputStream("TestEof.java"))); while(in.available() != 0) System.out.print((char)in.readByte()); } catch (IOException e) { System.err.println("IOException"); } } } ///:~
//: InFile.java // Shorthand class for opening an input file packagecom.bruceeckel.tools; import java.io.*; public class InFile extendsDataInputStream { public InFile(String filename) throws FileNotFoundException { super( new BufferedInputStream( new FileInputStream(filename))); } publicInFile(File file) throws FileNotFoundException { this(file.getPath()); } } ///:~
//: PrintFile.java // Shorthand class for opening an output file // for human-readable output. package com.bruceeckel.tools; import java.io.*; public classPrintFile extends PrintStream { public PrintFile(String filename) throwsIOException { super( new BufferedOutputStream( newFileOutputStream(filename))); } public PrintFile(File file) throws IOException {this(file.getPath()); } } ///:~
//: OutFile.java // Shorthand class for opening an output file // for data storage.package com.bruceeckel.tools; import java.io.*; public class OutFile extendsDataOutputStream { public OutFile(String filename) throws IOException {super( new BufferedOutputStream( new FileOutputStream(filename))); } publicOutFile(File file) throws IOException { this(file.getPath()); } } ///:~
//: Echo.java // How to read from standard input import java.io.*; public classEcho { public static void main(String[] args) { DataInputStream in = newDataInputStream( new BufferedInputStream(System.in)); String s; try { while((s = in.readLine()).length() != 0) System.out.println(s); // An empty line terminates the program } catch(IOException e) { e.printStackTrace(); } } } ///:~
//: SortedWordCount.java // Counts words in a file, outputs // results in sorted form. import java.io.*; import java.util.*; import c08.*; // Contains StrSortVectorclass Counter { private int i = 1; int read() { return i; } void increment() { i++; } }public class SortedWordCount { private FileInputStream file; privateStreamTokenizer st; private Hashtable counts = new Hashtable(); SortedWordCount(String filename) throws FileNotFoundException { try { file =new FileInputStream(filename); st = new StreamTokenizer(file); st.ordinaryChar('.'); st.ordinaryChar('-'); } catch(FileNotFoundException e) { System.out.println( "Could not open " + filename); throw e; } } void cleanup() {try { file.close(); } catch(IOException e) { System.out.println( "file.close() unsuccessful"); } } void countWords() { try { while(st.nextToken() != StreamTokenizer.TT_EOF) { String s; switch(st.ttype) { caseStreamTokenizer.TT_EOL: s = new String("EOL"); break; caseStreamTokenizer.TT_NUMBER: s = Double.toString(st.nval); break; caseStreamTokenizer.TT_WORD: s = st.sval; // Already a String break; default: // single character in ttype s = String.valueOf((char)st.ttype); }if(counts.containsKey(s)) ((Counter)counts.get(s)).increment(); elsecounts.put(s, new Counter()); } } catch(IOException e) { System.out.println("st.nextToken() unsuccessful"); } } Enumeration values() { returncounts.elements(); } Enumeration keys() { return counts.keys(); } Counter getCounter(String s) { return (Counter)counts.get(s); } Enumeration sortedKeys() { Enumeration e = counts.keys(); StrSortVector sv = newStrSortVector(); while(e.hasMoreElements()) sv.addElement((String)e.nextElement()); // This call forces a sort: returnsv.elements(); } public static void main(String[] args) { try { SortedWordCount wc = new SortedWordCount(args[0]); wc.countWords(); Enumeration keys = wc.sortedKeys(); while(keys.hasMoreElements()) { String key = (String)keys.nextElement(); System.out.println(key + ": " + wc.getCounter(key).read()); } wc.cleanup(); } catch(Exception e) { e.printStackTrace(); } } } ///:~
//: AnalyzeSentence.java // Look for particular sequences // within sentences.import java.util.*; public class AnalyzeSentence { public static void main(String[] args) { analyze("I am happy about this"); analyze("I am not happy about this"); analyze("I am not! I am happy"); analyze("I am sad about this"); analyze("I am not sad about this"); analyze("I am not! I am sad"); analyze("Are you happy about this?"); analyze("Are you sad about this?"); analyze("It's you! I am happy"); analyze("It's you! I am sad"); } static StringTokenizer st; static voidanalyze(String s) { prt("/nnew sentence >> " + s); boolean sad = false; st = newStringTokenizer(s); while (st.hasMoreTokens()) { String token = next(); // Look until you find one of the // two starting tokens: if(!token.equals("I") && !token.equals("Are")) continue; // Top of while loop if(token.equals("I")) { String tk2 = next(); if(!tk2.equals("am")) // Must be after I break; // Out of while loopelse { String tk3 = next(); if(tk3.equals("sad")) { sad = true; break; // Out of while loop } if (tk3.equals("not")) { String tk4 = next(); if(tk4.equals("sad"))break; // Leave sad false if(tk4.equals("happy")) { sad = true; break; } } } }if(token.equals("Are")) { String tk2 = next(); if(!tk2.equals("you")) break; // Must be after Are String tk3 = next(); if(tk3.equals("sad")) sad = true; break; // Out of while loop } } if(sad) prt("Sad detected"); } static String next() {if(st.hasMoreTokens()) { String s = st.nextToken(); prt(s); return s; } else return""; } static void prt(String s) { System.out.println(s); } } ///:~
Sources & Sinks: |
Corresponding Java 1.1 class |
InputStream |
Reader |
OutputStream |
Writer |
FileInputStream |
FileReader |
FileOutputStream |
FileWriter |
StringBufferInputStream |
StringReader |
(no corresponding class) |
StringWriter |
ByteArrayInputStream |
CharArrayReader |
ByteArrayOutputStream |
CharArrayWriter |
PipedInputStream |
PipedReader |
PipedOutputStream |
PipedWriter |
Filters:
Java 1.0 class
Corresponding Java 1.1 class
FilterInputStream |
FilterReader |
FilterOutputStream |
FilterWriter (abstract class with no subclasses) |
BufferedInputStream |
BufferedReader |
BufferedOutputStream |
BufferedWriter |
DataInputStream |
use DataInputStream |
PrintStream |
PrintWriter |
LineNumberInputStream |
LineNumberReader |
StreamTokenizer |
StreamTokenizer |
PushBackInputStream |
PushBackReader |
//: NewIODemo.java // Java 1.1 IO typical usage import java.io.*; public classNewIODemo { public static void main(String[] args) { try { // 1. Reading input by lines: BufferedReader in = new BufferedReader( new FileReader(args[0])); String s, s2 = new String(); while((s = in.readLine())!= null) s2 += s + "/n"; in.close(); // 1b. Reading standard input: BufferedReader stdin = newBufferedReader( new InputStreamReader(System.in)); System.out.print("Enter a line:"); System.out.println(stdin.readLine()); // 2. Input from memoryStringReader in2 = new StringReader(s2); int c; while((c = in2.read()) != -1) System.out.print((char)c); // 3. Formatted memory input try { DataInputStream in3 = new DataInputStream( // Oops: must use deprecated class: newStringBufferInputStream(s2)); while(true) System.out.print((char)in3.readByte()); } catch(EOFException e) { System.out.println("End of stream"); } // 4. Line numbering & file output try { LineNumberReader li = new LineNumberReader( new StringReader(s2)); BufferedReader in4 = new BufferedReader(li); PrintWriter out1 = newPrintWriter( new BufferedWriter( new FileWriter("IODemo.out"))); while((s = in4.readLine()) != null ) out1.println( "Line " + li.getLineNumber() + s); out1.close(); } catch(EOFException e) { System.out.println("End of stream"); } // 5. Storing & recovering data try { DataOutputStream out2 = newDataOutputStream( new BufferedOutputStream( newFileOutputStream("Data.txt"))); out2.writeDouble(3.14159); out2.writeBytes("That was pi"); out2.close(); DataInputStream in5 = newDataInputStream( new BufferedInputStream( new FileInputStream("Data.txt"))); BufferedReader in5br = new BufferedReader( new InputStreamReader(in5)); // Must use DataInputStream for data: System.out.println(in5.readDouble()); // Can now use the "proper" readLine(): System.out.println(in5br.readLine()); }catch(EOFException e) { System.out.println("End of stream"); } // 6. Reading and writing random access // files is the same as before. // (not repeated here)} catch(FileNotFoundException e) { System.out.println( "File Not Found:" + args[1]); } catch(IOException e) { System.out.println("IO Exception"); } } } ///:~
//: IOBug.java // Java 1.1 (and higher?) IO Bug import java.io.*; public classIOBug { public static void main(String[] args) throws Exception { DataOutputStream out = new DataOutputStream( new BufferedOutputStream(new FileOutputStream("Data.txt"))); out.writeDouble(3.14159); out.writeBytes("That was the value of pi/n"); out.writeBytes("This is pi/2:/n"); out.writeDouble(3.14159/2); out.close(); DataInputStream in = newDataInputStream( new BufferedInputStream( new FileInputStream("Data.txt"))); BufferedReader inbr = new BufferedReader( new InputStreamReader(in)); // The doubles written BEFORE the line of text // read back correctly:System.out.println(in.readDouble()); // Read the lines of text:System.out.println(inbr.readLine()); System.out.println(inbr.readLine()); // Trying to read the doubles after the line // produces an end-of-file exception:System.out.println(in.readDouble()); } } ///:~
//: Redirecting.java // Demonstrates the use of redirection for // standard IO in Java 1.1 import java.io.*; class Redirecting { public static void main(String[] args) { try { BufferedInputStream in = new BufferedInputStream( newFileInputStream( "Redirecting.java")); // Produces deprecation message:PrintStream out = new PrintStream( new BufferedOutputStream( newFileOutputStream("test.out"))); System.setIn(in); System.setOut(out); System.setErr(out); BufferedReader br = new BufferedReader( newInputStreamReader(System.in)); String s; while((s = br.readLine()) != null) System.out.println(s); out.close(); // Remember this! } catch(IOException e) { e.printStackTrace(); } } } ///:~
//: GZIPcompress.java // Uses Java 1.1 GZIP compression to compress // a file whose name is passed on the command // line. import java.io.*; importjava.util.zip.*; public class GZIPcompress { public static void main(String[] args) { try { BufferedReader in = new BufferedReader( new FileReader(args[0])); BufferedOutputStream out = new BufferedOutputStream( newGZIPOutputStream( 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( newFileInputStream("test.gz")))); String s; while((s = in2.readLine()) != null) System.out.println(s); } catch(Exception e) { e.printStackTrace(); } } } ///:~
//: ZipCompress.java // Uses Java 1.1 Zip compression to compress // any number of files whose names are passed // on the command line. importjava.io.*; import java.util.*; import java.util.zip.*; public class ZipCompress {public static void main(String[] args) { try { FileOutputStream f = newFileOutputStream("test.zip"); CheckedOutputStream csum = newCheckedOutputStream( f, new Adler32()); ZipOutputStream out = newZipOutputStream( new BufferedOutputStream(csum)); out.setComment("A test of Java Zipping"); // Can't read the above comment, though for(int i = 0; i < args.length; i++) { System.out.println( "Writing file " + args[i]); BufferedReader in = new BufferedReader( new FileReader(args[i])); out.putNextEntry(newZipEntry(args[i])); int c; while((c = in.read()) != -1) out.write(c); in.close(); } out.close(); // Checksum valid only after the file // has been closed!System.out.println("Checksum: " + csum.getChecksum().getValue()); // Now extract the files: System.out.println("Reading file"); FileInputStream fi = newFileInputStream("test.zip"); CheckedInputStream csumi = newCheckedInputStream( fi, new Adler32()); ZipInputStream in2 = newZipInputStream( new BufferedInputStream(csumi)); ZipEntry ze; System.out.println("Checksum: " + csumi.getChecksum().getValue()); while((ze = in2.getNextEntry()) != null) { System.out.println("Reading file " + ze); int x;while((x = in2.read()) != -1) System.out.write(x); } in2.close(); // Alternative way to open and read // zip files: ZipFile zf = new ZipFile("test.zip"); Enumeration e = zf.entries(); while(e.hasMoreElements()) { ZipEntry ze2 = (ZipEntry)e.nextElement(); System.out.println("File: " + ze2); // ... and extract the data as before } } catch(Exception e) { e.printStackTrace(); } } } ///:~
//: Worm.java // Demonstrates object serialization in Java 1.1 import java.io.*;class Data implements Serializable { private int i; Data(int x) { i = x; } publicString toString() { return Integer.toString(i); } } public class Worm implementsSerializable { // Generate a random int value: private static int r() { return (int)(Math.random() * 10); } private Data[] d = { new Data(r()), new Data(r()), newData(r()) }; private Worm next; private char c; // Value of i == number of segments Worm(int i, char x) { System.out.println(" Worm constructor: " + i); c = x; if(--i > 0) next = new Worm(i, (char)(x + 1)); } Worm() { System.out.println("Default constructor"); } public String toString() { String s =":" + c + "("; for(int i = 0; i < d.length; i++) s += d[i].toString(); s += ")"; if(next !=null) s += next.toString(); return s; } public static void main(String[] args) { Worm w = new Worm(6, 'a'); System.out.println("w = " + w); try { ObjectOutputStream out = new ObjectOutputStream( newFileOutputStream("worm.out")); out.writeObject("Worm storage"); 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(); System.out.println(s + ", w2 = " + w2); } catch(Exception e) { e.printStackTrace(); } try { ByteArrayOutputStream bout = newByteArrayOutputStream(); ObjectOutputStream out = newObjectOutputStream(bout); out.writeObject("Worm storage"); out.writeObject(w); out.flush(); ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream( bout.toByteArray())); String s = (String)in.readObject(); Worm w3 = (Worm)in.readObject(); System.out.println(s + ", w3 = " + w3); } catch(Exception e) { e.printStackTrace(); } } } ///:~
Worm constructor: 6 Worm constructor: 5 Worm constructor: 4 Worm constructor: 3 Worm constructor: 2 Worm constructor: 1 w = :a(262):b(100):c(396):d(480):e(316):f(398) Worm storage, w2 = :a(262):b(100):c(396):d(480):e(316):f(398) Worm storage, w3 = :a(262):b(100):c(396):d(480):e(316):f(398)
//: Alien.java // A serializable class import java.io.*; public class Alienimplements Serializable { } ///:~
//: FreezeAlien.java // Create a serialized output file import java.io.*; publicclass FreezeAlien { public static void main(String[] args) throws Exception { ObjectOutput out = new ObjectOutputStream( new FileOutputStream("file.x")); Alien zorcon = new Alien(); out.writeObject(zorcon); } } ///:~
//: ThawAlien.java // Try to recover a serialized file without the // class of object that's stored in that file. package c10.xfiles; import java.io.*; public classThawAlien { public static void main(String[] args) throws Exception { ObjectInputStream in = new ObjectInputStream( new FileInputStream("file.x")); Object mystery = in.readObject(); System.out.println( mystery.getClass().toString()); } } ///:~
//: Blips.java // Simple use of Externalizable & a pitfall import java.io.*; importjava.util.*; class Blip1 implements Externalizable { public Blip1() { System.out.println("Blip1 Constructor"); } public voidwriteExternal(ObjectOutput out) throws IOException { System.out.println("Blip1.writeExternal"); } public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { System.out.println("Blip1.readExternal"); } } class Blip2 implementsExternalizable { Blip2() { System.out.println("Blip2 Constructor"); } public voidwriteExternal(ObjectOutput out) throws IOException { System.out.println("Blip2.writeExternal"); } public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { System.out.println("Blip2.readExternal"); } } public class Blips { public staticvoid main(String[] args) { System.out.println("Constructing objects:"); Blip1 b1 =new Blip1(); Blip2 b2 = new Blip2(); try { ObjectOutputStream o = newObjectOutputStream( new FileOutputStream("Blips.out")); System.out.println("Saving objects:"); o.writeObject(b1); o.writeObject(b2); o.close(); // Now get them back: ObjectInputStream in = newObjectInputStream( new FileInputStream("Blips.out")); System.out.println("Recovering b1:"); b1 = (Blip1)in.readObject(); // OOPS! Throws an exception: //! System.out.println("Recovering b2:"); //! b2 = (Blip2)in.readObject(); } catch(Exception e) { e.printStackTrace(); } } } ///:~
Constructing objects: Blip1 Constructor Blip2 Constructor Saving objects: Blip1.writeExternal Blip2.writeExternal Recovering b1: Blip1 Constructor Blip1.readExternal
//: Blip3.java // Reconstructing an externalizable object import java.io.*; importjava.util.*; class Blip3 implements Externalizable { int i; String s; // No initialization public Blip3() { System.out.println("Blip3 Constructor"); // s, i not initialized } public Blip3(String x, int a) { System.out.println("Blip3(String x, int a)"); s = x; i = a; // s & i initialized only in non-default // constructor. } publicString toString() { return s + i; } public void writeExternal(ObjectOutput out)throws IOException { System.out.println("Blip3.writeExternal"); // You must do this: out.writeObject(s); out.writeInt(i); } public void readExternal(ObjectInput in)throws IOException, ClassNotFoundException { System.out.println("Blip3.readExternal"); // You must do this: s = (String)in.readObject(); i =in.readInt(); } public static void main(String[] args) { System.out.println("Constructing objects:"); Blip3 b3 = new Blip3("A String ", 47); System.out.println(b3.toString()); try { ObjectOutputStream o = newObjectOutputStream( new FileOutputStream("Blip3.out")); System.out.println("Saving object:"); o.writeObject(b3); o.close(); // Now get it back: ObjectInputStream in = new ObjectInputStream( newFileInputStream("Blip3.out")); System.out.println("Recovering b3:"); b3 = (Blip3)in.readObject(); System.out.println(b3.toString()); } catch(Exception e) { e.printStackTrace(); } } } ///:~
//: Logon.java // Demonstrates the "transient" keyword import java.io.*; importjava.util.*; class Logon implements Serializable { private Date date = newDate(); private String username; private transient String password; Logon(String name, String pwd) { username = name; password = pwd; } publicString toString() { String pwd = (password == null) ? "(n/a)" : password; return"logon info: /n " + "username: " + username + "/n date: " + date.toString() + "/n password: " + pwd; } public static void main(String[] args) { Logon a = newLogon("Hulk", "myLittlePony"); System.out.println( "logon a = " + a); try { ObjectOutputStream o = new ObjectOutputStream( newFileOutputStream("Logon.out")); o.writeObject(a); o.close(); // Delay: intseconds = 5; long t = System.currentTimeMillis() + seconds * 1000;while(System.currentTimeMillis() < t) ; // Now get them back:ObjectInputStream in = new ObjectInputStream( newFileInputStream("Logon.out")); System.out.println( "Recovering object at " +new Date()); a = (Logon)in.readObject(); System.out.println( "logon a = " + a); }catch(Exception e) { e.printStackTrace(); } } } ///:~
logon a = logon info: username: Hulk date: Sun Mar 23 18:25:53 PST 1997 password: myLittlePony Recovering object at Sun Mar 23 18:25:59 PST 1997 logon a = logon info: username: Hulk date: Sun Mar 23 18:25:53 PST 1997 password: (n/a)
private void writeObject(ObjectOutputStream stream) throws IOException;private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException
//: SerialCtl.java // Controlling serialization by adding your own // writeObject() and readObject() methods. import java.io.*; public class SerialCtl implementsSerializable { String a; transient String b; public SerialCtl(String aa, String bb) { a = "Not Transient: " + aa; b = "Transient: " + bb; } public String toString() {return a + "/n" + b; } private void writeObject(ObjectOutputStream stream)throws IOException { stream.defaultWriteObject(); stream.writeObject(b); }private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); b = (String)stream.readObject(); } public static void main(String[] args) { SerialCtl sc = new SerialCtl("Test1", "Test2"); System.out.println("Before:/n" + sc); ByteArrayOutputStream buf = new ByteArrayOutputStream(); try { ObjectOutputStream o = new ObjectOutputStream(buf); o.writeObject(sc); // Now get it back: ObjectInputStream in = new ObjectInputStream( newByteArrayInputStream( buf.toByteArray())); SerialCtl sc2 = (SerialCtl)in.readObject(); System.out.println("After:/n" + sc2); }catch(Exception e) { e.printStackTrace(); } } } ///:~
//: MyWorld.java import java.io.*; import java.util.*; class House implementsSerializable {} class Animal implements Serializable { String name; House preferredHouse; Animal(String nm, House h) { name = nm; preferredHouse = h; } public String toString() { return name + "[" + super.toString() + "], " + preferredHouse + "/n"; } } public class MyWorld { public static void main(String[] args) { House house = new House(); Vector animals = new Vector(); animals.addElement( new Animal("Bosco the dog", house)); animals.addElement( new Animal("Ralph the hamster", house)); animals.addElement( new Animal("Fronk the cat", house)); System.out.println("animals: " + animals); try { ByteArrayOutputStream buf1 =new ByteArrayOutputStream(); ObjectOutputStream o1 = newObjectOutputStream(buf1); o1.writeObject(animals); o1.writeObject(animals); // Write a 2nd set // Write to a different stream: ByteArrayOutputStream buf2 =new ByteArrayOutputStream(); ObjectOutputStream o2 = newObjectOutputStream(buf2); o2.writeObject(animals); // Now get them back:ObjectInputStream in1 = new ObjectInputStream( new ByteArrayInputStream( buf1.toByteArray())); ObjectInputStream in2 = new ObjectInputStream( newByteArrayInputStream( buf2.toByteArray())); Vector animals1 = (Vector)in1.readObject(); Vector animals2 = (Vector)in1.readObject(); Vector animals3 = (Vector)in2.readObject(); System.out.println("animals1: " + animals1); System.out.println("animals2: " + animals2); System.out.println("animals3: " + animals3); } catch(Exception e) { e.printStackTrace(); } } } ///:~
animals: [Bosco the dog[Animal@1cc76c], House@1cc769 , Ralph the hamster[Animal@1cc76d], House@1cc769 , Fronk the cat[Animal@1cc76e], House@1cc769 ] animals1: [Bosco the dog[Animal@1cca0c], House@1cca16 , Ralph the hamster[Animal@1cca17], House@1cca16 , Fronk the cat[Animal@1cca1b], House@1cca16 ] animals2: [Bosco the dog[Animal@1cca0c], House@1cca16 , Ralph the hamster[Animal@1cca17], House@1cca16 , Fronk the cat[Animal@1cca1b], House@1cca16 ] animals3: [Bosco the dog[Animal@1cca52], House@1cca5c , Ralph the hamster[Animal@1cca5d], House@1cca5c , Fronk the cat[Animal@1cca61], House@1cca5c ]
//: CADState.java // Saving and restoring the state of a // pretend CAD system.import java.io.*; import java.util.*; abstract class Shape implements Serializable { public static final int RED = 1, BLUE = 2, GREEN = 3; private int xPos, yPos, dimension; private static Random r = new Random(); private static int counter = 0; abstract public void setColor(int newColor); abstract public int getColor();public Shape(int xVal, int yVal, int dim) { xPos = xVal; yPos = yVal; dimension = dim; } public String toString() { return getClass().toString() + " color[" + getColor() + "] xPos[" + xPos + "] yPos[" + yPos + "] dim[" + dimension + "]/n"; }public static Shape randomFactory() { int xVal = r.nextInt() % 100; int yVal = r.nextInt() % 100; int dim = r.nextInt() % 100; switch(counter++ % 3) { default:case 0: return new Circle(xVal, yVal, dim); case 1: return new Square(xVal, yVal, dim); case 2: return new Line(xVal, yVal, dim); } } } class Circle extendsShape { private static int color = RED; public Circle(int xVal, int yVal, int dim) {super(xVal, yVal, dim); } public void setColor(int newColor) { color = newColor; } public int getColor() { return color; } } class Square extends Shape { privatestatic int color; public Square(int xVal, int yVal, int dim) { super(xVal, yVal, dim); color = RED; } public void setColor(int newColor) { color = newColor; } publicint getColor() { return color; } } class Line extends Shape { private static intcolor = RED; public static void serializeStaticState(ObjectOutputStream os)throws IOException { os.writeInt(color); } public static voiddeserializeStaticState(ObjectInputStream os) throws IOException { color = os.readInt(); } public Line(int xVal, int yVal, int dim) { super(xVal, yVal, dim); }public void setColor(int newColor) { color = newColor; } public int getColor() {return color; } } public class CADState { public static void main(String[] args)throws Exception { Vector shapeTypes, shapes; if(args.length == 0) { shapeTypes = new Vector(); shapes = new Vector(); // Add handles to the class objects: shapeTypes.addElement(Circle.class); shapeTypes.addElement(Square.class); shapeTypes.addElement(Line.class);// Make some shapes: for(int i = 0; i < 10; i++) shapes.addElement(Shape.randomFactory()); // Set all the static colors to GREEN: for(int i = 0; i < 10; i++) ((Shape)shapes.elementAt(i)) .setColor(Shape.GREEN); // Save the state vector: ObjectOutputStream out =new ObjectOutputStream( new FileOutputStream("CADState.out")); out.writeObject(shapeTypes); Line.serializeStaticState(out); out.writeObject(shapes); } else { // There's a command-line argumentObjectInputStream in = new ObjectInputStream( new FileInputStream(args[0]));// Read in the same order they were written: shapeTypes = (Vector)in.readObject(); Line.deserializeStaticState(in); shapes = (Vector)in.readObject(); } // Display the shapes: System.out.println(shapes); } }///:~
>java CADState [class Circle color[3] xPos[-51] yPos[-99] dim[38] , classSquare color[3] xPos[2] yPos[61] dim[-46] , class Line color[3] xPos[51] yPos[73] dim[64] , class Circle color[3] xPos[-70] yPos[1] dim[16] , classSquare color[3] xPos[3] yPos[94] dim[-36] , class Line color[3] xPos[-84] yPos[-21] dim[-35] , class Circle color[3] xPos[-75] yPos[-43] dim[22] , classSquare color[3] xPos[81] yPos[30] dim[-45] , class Line color[3] xPos[-29] yPos[92] dim[17] , class Circle color[3] xPos[17] yPos[90] dim[-76] ] >java CADState CADState.out [class Circle color[1] xPos[-51] yPos[-99] dim[38] ,class Square color[0] xPos[2] yPos[61] dim[-46] , class Line color[3] xPos[51] yPos[73] dim[64] , class Circle color[1] xPos[-70] yPos[1] dim[16] , classSquare color[0] xPos[3] yPos[94] dim[-36] , class Line color[3] xPos[-84] yPos[-21] dim[-35] , class Circle color[1] xPos[-75] yPos[-43] dim[22] , classSquare color[0] xPos[81] yPos[30] dim[-45] , class Line color[3] xPos[-29] yPos[92] dim[17] , class Circle color[1] xPos[17] yPos[90] dim[-76] ]