FilterInputStream 和 FilterOutputStream 是用来提供装饰器类接口以控制特定输入流(InputStream)和输出流(OutputStream)的两个类,它们分别自I/O类库中的基类InputStream和OutputStream派生而来,这两个类是装饰器的必要条件(以便能为所有正在被修饰的对象提供通用接口)。
DataInputStream 允许我们读取不同的基本数据类型以及String对象(所有方法都以“read”开头,例如readByte()、readFloat()等等);搭配相应的DataOutputStream,我们就可以通过数据“流”将基本类型的数据从一个地方迁移到另一个地方,具体迁移地方由InputStream类型的类决定。
DataOutputStream 可以将基本数据类型以及String对象格式化输出到“流”中(所有方法都以“write”开头,例如writeByte()、writeFloat()等等);这样一来,任何机器上的任何DataInputStream都能够读取它们(即是DataInputStream和DataOutputStream可以跨平台使用)。
适配器类:InputStreamReader可以把InputStream转换为Reader,而OutputStreamWriter可以把OutputStream转换为Writer
RandomAccessFile 适用于由大小已知的记录组成的文件,所以我们可以使用seek()将记录从一处转移到另一处,然后读取或者修改记录。
如果我们从DataInputStream用readByte()一次一个字节地读取字符,那么任何字节的值都是合法的结果,因此返回值不能用来检测输入是否结束。相反,我们可以使用available()方法查看还有多少可供存取的字符。下面例子演示怎样一次一个字节地读取文件:
public class TestEOF{ public static void main(String[] args) throws IOException{ DataInputStream dis = new DataInputStream(new BufferedInputStream( new FileInputStream("TestEOF.java"))); while(dis.available()!=0) System.out.println((char)dis.readByte()); } } 基本的文件输出FileWriter对象可以向文件写入数据。首先,创建一个与指定文件连接的FileWriter。实际上,我们通常会用BufferWriter将其包装起来用以缓冲输出(缓冲往往能显示增加I/O操作的性能)。本例中,为了提供格式化机制,它被装饰成了PrintWriter:
public class BasicFileOutput{ static String file = "BasicFileOutput.out"; public static void main(String[] args) throws IOException{ BufferReader br = new BufferReader(new StringReader( BufferedInputFile.read("BasicFileOutput.java"))); PrintWriter pw = new PrintWriter(new BufferWriter( new FileWriter(file))); int lineCount = 1; //行号 String s; while((s = br.readLine())!=null) pw.println(lineCount++ + ":" + s); pw.close(); //将写出的文件输出 System.out.println(BufferedInputFile.read(file)); } }文本文件输出的快捷方式
PrintWriter中添加了一个辅助构造器,使得你不必在每次希望创建文本文件并向其中写入时,都去执行所有的装饰工作。
public class FileOutputShortcut{ static String file = "FileOutputShortcut.out"; public static void main(String[] args) throws IOException{ BufferReader br = new BufferReader(new StringReader( BufferedInputFile.read("FileOutputShortcut.java"))); PrintWriter pw = new PrintWriter(file); String s; int lineCount = 1; while((s = br.readLine())!=null) pw.println(lineCount++ + ":" + s); System.out.println(BufferedInputFile.read(file)); } } 存储和恢复数据PrintWriter可以对数据进行格式化,以便人们的阅读。但是为了输出可供另一个“流”恢复的数据,我们需要用DataOutputStream写入数据,并用DataInputStream恢复数据。
public class StoringAndRecoveringData{ public static void main(String[] args) throws IOException{ DataOutputStream dos = new DataOutputStream(new BufferOutputStream( new FileOutputStream("Data.txt"))); //写数据到Data.txt dos.writeDouble(3.14159); dos.writeUTF("That was pi"); dos.writeDouble(1.41413); dos.writeUTF("Square root of 2"); dos.close(); DataInputStream dis = new DataInputStream(new BufferInputStream( new FileInputStream("Data.txt"))); //读取文件Data.txt System.out.println(dis.readDouble()); //readUTF()和writeUTF()的使用适合于java的UTF-8遍体,非java程序读写UTF-8,必须编写特殊代码才能正确读取字符串 System.out.println(dis.readUTF()); System.out.println(dis.readDouble()); System.out.println(dis.readUTF()); } } 读取随机访问文件使用RandomAccessFile,类似于组合使用了DataInputStream和DataOutputStream,你必须直到文件排版,这样才能正确地操作它。RandomAccessFile拥有读取基本类型和UTF-8字符串的各种具体方法。
public class UsingRandomAccessFile{ static String file = "rtest.dat"; static void displayt() throws IOException{ RandomAccessFile raf = new RandomAccessFile(file,"r"); for(int i = 0; i < 7; i++) System.out.println("Value" + i + ":" + raf.readDouble()); System.out.println(raf.readUTF()); raf.close(); } public static void main(String[] args) throws IOException{ RandomAccessFile raf = new RandomAccessFile(file,"rw"); for(int i = 0; i < 7; i++) raf.writeDouble(i*1.414); System.out.println("The end of the file"); display(); raf = new RandomAccessFile(file,"rw"); raf.seek(5*8); //double是8字节长,所以为了用seek()查找第5个双精度值,只需用5*8来产生查找位置 raf.writeDouble(47.0001); raf.close(); display(); } }