输入有关的所有类都从InputStream继承,与输出有关的所有类都从OutputStream继承。
利用层次化对象动态和透明地添加单个对象的能力的做法叫做“装饰器”方案。
RandomAccessFile不属于InputStream或者OutputStream分层结构的一部分。只能针对
文件才能操作,不能针对数据流操作。可以在一个文件里向前或向后移动。
public interface FilenameFilter {
boolean accept(文件目录, 字串名);
}
通过实现这个接口,可以对文件名进行过滤。下面用的是匿名内部类来实现这个接口。
package exam;
import java.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();
else
list=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
package c10;
import java.io.*;
import oypj.tools.*;
public class IOStreamDemo {
public static void main(String[] args){
try{
//1.Buffered input file
DataInputStream in=new DataInputStream(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=new StringBufferInputStream(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){
P.rintln("End of stream encountered");
}
//4.Line numbering & file output
try{
LineNumberInputStream li=new LineNumberInputStream(new StringBufferInputStream(s2));
DataInputStream in4=new DataInputStream(li);
PrintStream out1=new PrintStream(new BufferedOutputStream(new FileOutputStream("IOEemo.out")));
while((s=in4.readLine())!=null)
out1.println("Line"+li.getLineNumber()+s);
out1.close();
}catch(EOFException e){
P.rintln("End of stream encountered");
}
//5.Storing &recovering data
try{
DataOutputStream out2=new DataOutputStream(new BufferedOutputStream(new FileOutputStream("Data.txt")));
out2.writeBytes("Here's the value of pi:\n");
out2.writeDouble(3.1415926);
out2.close();
DataInputStream in5=new DataInputStream(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=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();
//7.File inout 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 shorthand
PrintFile out3=new PrintFile("Data2.txt");
out3.print("Test of PrintFile");
out3.close();
//9.Data file output shorthand
OutFile out4=new OutFile("Data.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");
}
}
}
System.out和System.err已预封装成一个PrintStream对象,System.in是一个原始的InputStream。
能直接使用System.out和System.err,但是System.in要先封装,才能从中读取数据。例如:
package c10;
import java.io.*;
public class Echo {
public static void main(String[] args){
DataInputStream in=new DataInputStream(new BufferedInputStream(System.in));
String s;
try{
while((s=in.readLine()).length()!=0)
System.out.println(s);
}catch(IOException e){
e.printStackTrace();
}
}
}
StreamTokenizer用于将任何InputStream分割为一系列“记号”(Token),可以用来计算各个单
词在文本文件中重复出现的次数。
StringTokenizer的作用是每次返回字串内的一个记号,字串“Where is my cat?” 的记号分别是
“Where”、“is”、“my”、“cat?”
下面的例子使用了新的IO流
package c10;
import java.io.*;
public class NewIODemo {
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=new BufferedReader(new InputStreamReader(System.in));
System.out.print("Enter a line");
System.out.println(stdin.readLine());
//2.Input from memory
StringReader in2=new StringReader(s2);
int c;
while((c=in2.read())!=-1)
System.out.println((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");
}
//4.Line numbering &file output
try{
LineNumberReader li=new LineNumberReader(new StringReader(s2));
BufferedReader in4=new BufferedReader(li);
PrintWriter out1=new PrintWriter(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=new DataOutputStream(new BufferedOutputStream(new FileOutputStream("data.txt")));
out2.writeDouble(3.14159);
out2.writeBytes("That was pi");
out2.close();
DataInputStream in5=new DataInputStream(new BufferedInputStream(new FileInputStream("Data.txt")));
BufferedReader in5br=new BufferedReader(new InputStreamReader(in5));
System.out.println(in5.readDouble());
System.out.println(in5br.readLine());
}catch(EOFException e){
System.out.println("End of stream");
}
}catch(FileNotFoundException e){
System.out.println("File Not Found:"+args[1]);
}catch(IOException e){
System.out.println("IO Exception");
}
}
}
下面这个例子展示了Java 1.1本身的一个错误。在writeBytes()调用后,后面写入的其他数据都不能够
恢复。
package c10;
import java.io.*;
public class IOBug {
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("That is pi/2:\n");
out.writeDouble(3.14159/2);
out.close();
DataInputStream in=new DataInputStream(new BufferedInputStream(new FileInputStream("Data.txt")));
BufferedReader inbr=new BufferedReader(new InputStreamReader(in));
System.out.println(in.readDouble());
System.out.println(inbr.readLine());
System.out.println(inbr.readLine());
System.out.println(in.readDouble());
}
}
输出结果: 3.14159/2的值没有恢复出来
setIn(InputStream)、setOut(PrintStream)、setErr(PrintStream),下面是使用的例子
package c10;
import java.io.*;
public class Redirecting {
public static void main(String[] args){
try{
BufferedInputStream in=new BufferedInputStream(new FileInputStream("F:/javatest/exam/src/c10/Redirecting.java"));
PrintStream out=new PrintStream(new BufferedOutputStream(new FileOutputStream("test.txt")));
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();
}catch(IOException e){
e.printStackTrace();
}
}
}
GZIP接口,适合只有单个数据流。Zip可以保存多个文件,对于要加入压缩档的每一个文件,
都必须调用putNextEntry(),对应的有getNextEntry()。
只需要将输出流封装到一个GZIPOutputStream或者ZipOutputStream内,将输入流封装到
GZIPInputStream或者ZipInputStream内即可,剩余的全部操作就是标准的io读写。
可以用ZipFile对象读取文件,该对象有entries()方法,可以为ZipEntry返回一个Enumeration.
Checksum:Adler32(速度快一些)和CRC32(慢一些,但更准确)。
ZipEntry只支持CRC接口
作用是将一系列文件合并到单个压缩文件里。JAR文件由一系列采用Zip压缩格式的文件构成,同时
还有一张“详情单”。
面向实现Serializeble接口的对象,可将它们转换成一系列字节,可在以后完全恢复回原来的样子。
首先要创建某些OutputStream对象,然后将其封装到ObjectOutputStream对象内,然后再调用writeObject()
就可以完成对象的序列化。相反的过程是将一个InputStream封装到ObjectInputStream内,然后调用readObject()
恢复了一个序列化的对象后,如果想对其做更多的事情,必须保证JVM能在本地类路径或者因特网的其他地方找到
相关的.class文件。
通过实现Externalization接口,便可以控制序列化的具体过程。这个接口中有writeExternal()和readExternal()方法。
Serializable的对象完全以它保存下来的二进制位为基础恢复,不存在构建器的调用。而Externalizable对象,所有普通
的默认构建器会执行,然后调用readExternal(),所以默认构建器要设置为public。
transient(临时)关键字 ,可以用来逐个字段地关闭序列化。
Externalizable的替代方法:实现Serializable接口,并添加writeObject()和readObject()的方法。可以
调用defaultWriteObject(),从而采取默认的writeObject()行动,相反地可以调用defaultReadObject()。
private void
writeObject(ObjectOutputStream stream)
throws IOException;
private void
readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException
想序列化static值,必须亲自动手,自动序列化的时候会出错。
这一章给我的感觉就是Java的输入输出非常复杂,但是采用了装饰器方案,确实可以灵活地使用各种操作。
对象的序列化给我们保存和恢复对象提供了方便,而且与平台无关。还提供了压缩类,这是我之前没有了解过的。