1. 在上一讲中我们介绍过节点流和过滤流,节点流是直接与目标打交道的,比如说文件,键盘等,但是什么是节点流,什么是过滤流呢?通过这个图我们来看一下。
下面这个图表示的InputStream的类层次,当然接下去同样会降到OutputStream的情况。
图91-1:Java.io包中InputStream的类层次
对于InputStream来说有很多子类如上图所示,里面有一个FilterInputStream,查看JDK Doc文档中FilterInputStream
public class FilterInputStreamextends InputStream
A FilterInputStream contains some other input stream, which it uses as its basic source of data[一个FilterInputStream包含了其他的输入流,它将其他的输入流做为它的基本来源]也就是说他是一个过滤流,它会包含了其他的节点流
【注意:我们一般不会直接的去使用FilterInputStream,我们一般会使用他们的子类,这些子类都是过滤流,它们会包装了其他的节点流,也就具备了它特性的功能,比如说BufferInputStream过滤流可以包含了FileInputStream,这这个文件流就具备了缓冲的功能】
2.前面我们重点了讲了输入流,下面我们将一下输出流OutputStream
1)OutputStream是定义了流式字节输出模式的抽象类。该类的所有方法返回一个void 值并且在出错情况下引发一个IOException异常。
2) 通过打开一个到目标的输出流,程序可以向外部目标顺序写数据
图91-2:输出流
3.Output下节点流和过滤流
图91-3:java.io包中OutputStream的类层次
程序demo:练习一下OutputStream里面一些方法
package com.ahuier.io2; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.OutputStream; public class OutputStreamTest1 { public static void main(String[] args) throws Exception { /* * 对于文件输出流来说,如果在c:/out.txt目录下有这个文件的话,就将里面文件清空,然后写新的内容 * 如果该目录下没有文件的话,就新建一个文件,然后将内容写到这个文件中 * OutputStream os = new FileOutputStream("c:/out.txt", true);则往原有的文件内容追加数据 */ OutputStream os = new FileOutputStream("c:/out.txt"); String str = "helloword"; //调用String里面的getBytes()方法,获取改字符串的字节数组 byte[] buffer = str.getBytes(); os.write(buffer); //将buffer字节数组的内容写到os文件输出流里面,就会写到out.txt文件里面了 os.close(); } }
编译执行结果会在c盘目录下生成out.txt,并且将helloworld内容写入这个文件里面。
4. BufferOutputStream带缓冲的输出流,当然相应的还有带缓冲的输入流BufferInputStream,这边我们讲一下前者的使用方式:
查看JDK文档:BufferedOutputStream
public class BufferedOutputStream extends FilterOutputStream
The class implements a buffered output stream. By setting up such an output stream, an application can write bytes to the underlying output stream without necessarily causing a call to the underlying system for each byte written.
[这个类提供了缓冲的输出流,通过这样的一个输出流,应用可以写到一个底层的输出流中而不用导致每一调用系统都要去写一次字节]也就是如果我们不使用缓冲,那么每调用一次,我们都要往文件里面写一下,比如有100个字节就写一百次,由于IO的处理速度远小于CPU的处理速度,所以这种频繁的写数据势必会造成读写效率的下降,所以引入了缓冲输出流的概念。
编译执行结果后刷新一下工程会在工程底下生成一个1.txt文件,文件内容是写入的数组内容package com.ahuier.io2; import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.OutputStream; public class BufferedOutputStreamTest1 { public static void main(String[] args) throws Exception { OutputStream os = new FileOutputStream("1.txt"); /* * 将节点流FileOutputStream的os进行过滤流BufferedOutputStream的包装bos * 使得bos既可以实现对文件的输出,同时又具有了缓冲的功能 */ BufferedOutputStream bos = new BufferedOutputStream(os); bos.write("www.google.com".getBytes()); /* 注意如果这两行代码没有执行,则1.txt文件里面的内容为空,因为它是缓冲,它暂存在内存的缓冲区,没有写到文件中 * 如何让其写入呢?两种方法 * 第一种使用方法 flush()方法来清空缓冲的输出流,强制将缓冲的内容写到文件中 * 第二种使用close()方法它会在关闭之前写入文件 bos.close(); os.close();*/ bos.close(); os.close(); } }
5. ByteArrayInputStream (字节数组输入流)
(1)ByteArrayInputStream是把字节数组当成源的输入流。而FileInputStream是将文件当成源。
该类有两个构造方法,每个构造方法需要一个字节数组提供数据源
ByteArrayInputStream(byte array[ ])
ByteArrayInputStream(byte array[ ], int start, int numBytes)
这里,array是输入源。第二个构造方法创建了一个InputStream类,该类从字节数组的子集生成,以start指定索引的字符为起点,长度由numBytes决定
(2)下面的例子创建了两个ByteArrayInputStream,用字母表的字节表示初始化它们
import java.io.*;
class ByteArrayInputStreamDemo {
public static void main(String args[]) throws IOException {
String tmp = "abcdefghijklmnopqrstuvwxyz";
byte b[] = tmp.getBytes();
ByteArrayInputStream input1 = new ByteArrayInputStream(b);
ByteArrayInputStream input2 = new ByteArrayInputStream(b, 0, 3);
}
}
【说明】input1对象包含整个字母表中小写字母,input2仅包含开始的三个字母。(3)程序Demo
package com.ahuier.io2; import java.io.ByteArrayInputStream; public class ByteArrayInputStreamTest1 { public static void main(String[] args) { String temp = "abc"; byte[] b = temp.getBytes(); ByteArrayInputStream in = new ByteArrayInputStream(b); for(int i = 0; i < temp.length(); i++){ int c; //注意这边是按一个一个字节读取,int是32位,字节是8位,所以它是读取低八位的数值 while(-1 != (c = in.read())){ if(0 == i){ //注意这边(char)c是因为Java里面的字符都是用数数字区表示的,也就是用整型去表示的,所以要转换为char System.out.println((char)c); } else{ System.out.println(Character.toUpperCase((char)c)); } } System.out.println(); in.reset(); //对流的位置进行重置,它会调用mark()方法进行标记,查看JDK InputStream中的reset()方法,这种方式很少用 } } }
编译执行结果:a
b
c
A
B
C
A
B
C
6. ByteArrayOutputStream(字节数组输出流)
ByteArrayOutputStream是一个把字节数组当作输出流的实现。
package com.ahuier.io2; import java.io.ByteArrayOutputStream; import java.io.FileOutputStream; import java.io.OutputStream; public class ByteArrayOutputStreamTest1 { public static void main(String[] args) throws Exception { ByteArrayOutputStream f = new ByteArrayOutputStream(); String str = "hello world welcome"; byte[] buffer = str.getBytes(); /* * 查看JDK文档中OutputStream的write(byte[] b) * 直接将buffer数据写入ByteArrayOutputStream里面去了 */ f.write(buffer); /* * 将ByteArrayOutputStream的字节再拿出来打印出来 * 使用toByteArray()将流里面的内容又转换成字节数组 */ byte[] result = f.toByteArray(); for(int i = 0; i < result.length; i++){ System.out.println((char)result[i]); } OutputStream os = new FileOutputStream("test.txt"); //通过这个writeTo()把f里面的字节数组写到了os流里面的test.txt文件里面去 f.writeTo(os); os.close(); } }
编译执行结果,这里不贴出来了,注意刷新Eclipse工程目录下test.txt文件里面也有写入