流(Stream)是字节的源或目的。
两种基本的流是:输入流(Input Stream)和输出流(Output Stream)。可从中读出一系列字节的对象称为输入流。而能向其中写入一系列字节的对象称为输出流。
FileInputStream和FileOutputStream
节点流,用于从文件中读取或往文件中写入字节流。如果在构造FileOutputStream时,文件已经存在,则覆盖这个文件。
BufferedInputStream和BufferedOutputStream
过滤流,需要使用已经存在的节点流来构造,提供带缓冲的读写,提高了读写的效率。
DataInputStream和DataOutputStream
过滤流,需要使用已经存在的节点流来构造,提供了读写Java中的基本数据类型的功能。
PipedInputStream和PipedOutputStream
管道流,用于线程间的通信。一个线程的PipedInputStream对象从另一个线程的PipedOutputStream对象读取输入。要使管道流有用,必须同时构造管道输入流和管道输出流。
- //用FileInputStream和FileOutputStream文件读写
- import java.io.*;
- public class StreamTest {
- public static void main(String[] args) throws Exception {
- /*int data;
- while((data=System.in.read())!=-1) {//读用户输入数据
- System.out.write(data);写出用户读入数据*/
- //写文件
- FileOutputStream fos = new FileOutputStream("1.txt");
- fos.write("http://www.windycool.com".getBytes());
- fos.close();
- //读文件
- FileInputStream fis = new FileInputStream("1.txt");
- byte[] buf = new byte[100];
- int len = fis.read(buf);
- System.out.println(new String(buf,0,len));
- fis.close();
- }
- }
- //用BufferedInputStream和BufferedOutputStream文件读写
- /*
- 作为另一种输入流,BufferedInputStream 为添加了功能,即缓冲输入和支持
- mark 和 reset 方法的能力。创建 BufferedInputStream 时即创建了一个
- 内部缓冲区数组。读取或跳过流中的各字节时,必要时可根据所包含的输入流再次
- 填充该内部缓冲区,一次填充多个字节。mark 操作记录输入流中的某个点,reset
- 操作导致在从所包含的输入流中获取新的字节前,再次读取自最后一次 mark 操作
- 以来所读取的所有字节。
- */
- import java.io.*;
- public class StreamTest {
- public static void main(String[] args) throws Exception {
- FileOutputStream fos = new FileOutputStream("1.txt");
- BufferedOutputStream bos = new BufferedOutputStream(fos);
- bos.write("http://www.windycool.com".getBytes());
- // bos.flush();
- bos.close();//将fos流链接到了bos流,关闭只需关闭尾端的bos流
- FileInputStream fis = new FileInputStream("1.txt");
- BufferedInputStream bis = new BufferedInputStream(fis);
- byte[] buf = new byte[100];
- int len=bis.read(buf);
- System.out.println(new String(buf,0,len));
- bis.close();
- }
- }
- /*
- public class PipedInputStream
- extends InputStream
- 传送输入流应该连接到传送输出流;传送输入流会提供要写
- 入传送输出流的所有数据字节。通常,数据由某个线程从
- PipedInputStream 对象读取,并由其他线程将其写入到相应的
- PipedOutputStream。不建议对这两个对象尝试使用单个线程,
- 因为这样可能会死锁该线程。传送输入流包含一个缓冲区,可在缓冲
- 区限定的范围内将读操作和写操作分离开。
- public class PipedOutputStream
- extends OutputStream
- 传送输出流可以连接到传送输入流,以创建通信管道。传送输出流
- 是管道的发送端。通常,数据由某个线程写入 PipedOutputStream
- 对象,并由其他线程从连接的 PipedInputStream 读取。不建议对
- 这两个对象尝试使用单个线程,因为这样可能会死锁该线程。
- */
- import java.io.*;
- public class PipedStreamTest {
- public static void main(String[] args) {
- PipedOutputStream pos = new PipedOutputStream();
- PipedInputStream pis = new PipedInputStream();
- try {
- pos.connect(pis);
- new Producer(pos).start();
- new Consumer(pis).start();
- }
- catch(Exception e) {
- e.printStackTrace();
- }
- }
- }
- class Producer extends Thread {
- private PipedOutputStream pos;
- public Producer(PipedOutputStream pos) {
- this.pos = pos;
- }
- public void run() {
- try {
- pos.write("Hello,welcome you!".getBytes());
- pos.close();
- }
- catch(Exception e) {
- e.printStackTrace();
- }
- }
- }
- class Consumer extends Thread {
- private PipedInputStream pis;
- public Consumer(PipedInputStream pis) {
- this.pis=pis;
- }
- public void run() {
- try {
- byte[] buf = new byte[100];
- int len = pis.read(buf);
- System.out.println(new String(buf,0,len));
- pis.close();
- }
- catch(Exception e) {
- e.printStackTrace();
- }
- }
- }
- //输出 Hello,welcome you!
Java的I/O库提供了一个称做链接的机制,可以将一个流与另一个流首尾相接,形成一个流管道的链接。这种机制实际上是一种被称为Decorator(装饰)设计模式的应用。
通过流的链接,可以动态的增加流的功能,而这种功能的增加是通过组合一些流的基本功能而动态获取的。
我们要获取一个I/O对象,往往需要产生多个I/O对象,这也是Java I/O库不太容易掌握的原因,但在I/O库中Decorator模式的运用,给我们提供了实现上的灵活性。
更多孙鑫lesson 7