zoukankan      html  css  js  c++  java
  • java jdk7学习笔记:InputStream与OutputStream .

    InputStreamOutputStream

              想活用输入/输出API,一定要先了解Java中如何以串流(Stream)抽象化输入/输出概念,以及InputStream、OutputStream继承架构。如此一来,无论标准输入/输出、文档输入/输出、网络输入/输出、数据库输入/输出等都可用一致的操作进行处理。

    串流设计的概念

         Java将输入/输出抽象化为串流,数据有来源及目的地,衔接两者的是串流对象。比喻来说,数据就好比水,串流好比水管,通过水管的衔接,水由一端流向另一端,如图1所示。

    串流衔接来源与目的地

          从应用程序角度来看,如果要将数据从来源取出,可以使用输入串流,如果要将数据写入目的地,可以使用输出串流。在Java中,输入串流代表对象为java.io.InputStream实例,输出串流代表对象为java.io.OutputStream实例。无论数据源或目的地为何,只要设法取得InputStream或OutputStream的实例,接下来操作输入/输出的方式都是一致,无须理会来源或目的地的真正形式,如图2所示

     

    从应用程序看InputStream与OutputStream

     来源与目的地都不知道的情况下,如何撰写程序?听来不可思议,但实际上就是会有这类需求。举个例子来说,可以设计一个通用的dump()方法:

    Stream IO.java

     

    package cc.openhome;

     

     

     

    import java.io.*;

     

     

     

    public class IO {

     

     

    u  数据来源与目的地

        public static void dump(InputStream src, OutputStream dest)

     

     

    v     客户端要处理异常

                                   throws IOException {

     

     

    w     尝试自动关闭资源

            try (InputStream input = src; OutputStream output = dest) {

     

     

    x    尝试每次从来源读取1024字节

                byte[] data = new byte[1024];

     

     

    y     读取数据

                int length = -1;

     

                while ((length = input.read(data)) != -1) {

     

     

    z  写出数据

                    output.write(data, 0, length);

     

                }

     

            }

     

        }

     

    }

     

    dump()方法接受InputStream与OutputStream实例,分别代表读取数据的来源,以及输出数据的目的地u。在进行InputStream与OutputStream的相关操作时若发生错误,会抛出java.io.IOException异常,在这里不特别处理,而是在dump()方法上声明throws,由调用dump()方法的客户端处理v。

     

          在不使用InputStream与OutputStream时,必须使用close()方法关闭串流。由于InputStream与OutputStream操作了java.io.Closeable接口,其父接口为java.lang.AutoCloseable接口,因此可使用JDK7尝试自动关闭资源语法w。

     

     

     

     

    思考一下,如果不能使用JDK7尝试自动关闭资源语法,那使用trycatchfinally该怎么写?可以参考一下8.2.2节的内容。

     

     

           每次从InputStream读入的数据,都会先置入byte数组中x,InputStream的read()方法,每次会尝试读入byte数组长度的数据,并返回实际读入的字节,只要不是-1,就表示读取到数据y。可以使用OutputStream的write()方法,指定要写出的byte数组、初始索引与数据长度z。

     

    那么这个dump()方法的来源是什么?不知道。目的地呢。也不知道。dump()方法并没有限定来源或目的地真实形式,而是依赖于抽象的InputStream、OutputStream。如果要将某个文档读入并另存为另一个文档,则可以这么使用:

     

    Stream Copy.java

     

    package cc.openhome;

     

     

     

    import java.io.*;

     

     

     

    public class Copy {

     

        public static void main(String[] args) throws IOException {

     

            IO.dump(

     

                  new FileInputStream(args[0]),

     

                  new FileOutputStream(args[1])

     

            );

     

        }

     

    }

     

            这个程序可以由命令行自变量指定读取的文档来源与写出的目的地,例如:

     

    > java cc.openhome.Copy c:\workspace\Main.java C:\workspace\Main.txt

     

    稍后就会介绍串流继承架构,FileInputStream是InputStream的子类,用于衔接文档以读入数据,FileOutputStream是OutputStream的子类,用于衔接文档以写出数据。

     

             如果要从HTTP服务器读取某个网页,并另存为文档,也可以使用这里设计的dump()方法。例如:

     

    Stream Download.java

     

    package cc.openhome;

     

     

     

    import java.io.*;

     

    import java.net.URL;

     

     

     

    public class Download {

     

        public static void main(String[] args) throws IOException {

     

            URL url = new URL(args[0]);

     

            InputStream src = url.openStream();

     

            OutputStream dest = new FileOutputStream(args[1]);

     

            IO.dump(src, dest);

     

        }

     

    }

     

            虽然没有正式介绍到网络程序设计,不过java.net.URL的使用很简单,只要指定网址,URL实例会自动进行HTTP协议。可以使用openStream()方法取得InputStream实例,代表与网站连接的数据串流。可以这样指定网址下载文档:

     

    > java cc.openhome.Download http://openhome.cc c:\workspace\index.txt

     

            无论来源或目的地实体形式为何,只要想办法取得InputStream或OutputStream,接下来都是调用InputStream或OutputStream的相关方法。例如,使用java.net.ServerSocket接受客户端联机的例子:

     

    ServerSocket server = null;

     

    Socket client = null;

     

    try {

     

        server = new ServerSocket(port);

     

        while(true) {

     

            client = server.accept();

     

            InputStream input = client.getInputStream();

     

            OutputStream output = client.getOutputStream();

     

            // 接下来就是操作 InputStream、OutputStream 实例了

     

            ...

     

        }

     

    }

     

    catch(IOException ex) {

     

        ...

     

    }

     

    如果将来学到Servlet,想将文档输出至浏览器,也会有类似的操作:

     

    response.setContentType("application/pdf");

     

    InputStream in = this.getServletContext()

     

                         .getResourceAsStream("/WEB-INF/jdbc.pdf");

     

    OutputStream out = response.getOutputStream();

     

    byte[] data = new byte[1024];

     

    int length = -1;

     

    while((length = in.read(data)) != -1) {

     

        out.write(data, 0, length);

     

    }

     

     

     

     

     

    本文摘自:《java jdk7学习笔记》林信良 5年沉积之作

    互动网:
    http://product.china-pub.com/199212

    当当网:http://product.dangdang.com/product.aspx?product_id=22643687

    作者: 林信良 [作译者介绍]
    出版社:清华大学出版社
    ISBN:9787302282082
    上架时间:2012-4-1
    出版日期:2012 年4月
    开本:16开
    页码:562
    版次:1-1

     

     

  • 相关阅读:
    PAT 甲级1135. Is It A Red-Black Tree (30)
    AVL树模板
    定时器模板
    Listview模板
    Hash二次探测
    BFS小结
    STL之set篇
    完全二叉树-已知中序排序,输出广度排序
    BZOJ2037: [Sdoi2008]Sue的小球
    poj1157LITTLE SHOP OF FLOWERS
  • 原文地址:https://www.cnblogs.com/tupbook/p/2443341.html
Copyright © 2011-2022 走看看