Java基础 - I/O的第一个层次

来源:互联网 发布:淘宝客微信二合一 编辑:程序博客网 时间:2024/05/21 12:41

 

所谓我理解的学习Java I/O的第一个层次

作者:写写心情的猪

参考资料:<<Java I/O>>2rd Edition

Java's I/O libraries are designed in an abstract way that enables you to read from external data sources and write to external targets, regardless of the kind of thing you're writing to or reading from. You use the same methods to read from a file that you do to read from the console or from a network connection. You use the same methods to write to a file that you do to write to a byte array or a serial port device.

PS:我觉得理解IO的第一个层次就是会使用InputStreamOutputStream这两个抽象类,只了解一点点它们的子类(只知道子类名字,不知道具体用法)。

具体来讲就是知道有InputStreamOutputStream这两个抽象类,它们是很多具有专门用途的IO类的父类,这些具有专门用途的IO类不必要去了解。你只要通过这两个类去读取或写入,而不管是从网络读取或丛文件读取(还可以从很多其他地方存取,蓝牙,串口设备。。)。所以了解和会使用这两个类,你的Java程序也就打开了跟外部的大门。(实际上这两个类很好使用,只有很少的方法)

 

       “这些具有专门用途的IO类可以先不必要去了解,你只要通过这两个类去读取或写入” 这句话可以这么理解

比如,URLConnection这个类有个public OutputStream getOutputStream( ) throws IOException 方法,可以返回一个OutputStream

       URLConnection con = new URLConnection(URL u);

       OutputStream out = con.getOutputStream();

       这里的out是什么呢?只是一个OutputStream类吗?显然不是,这个OutputStream是某个具体的IO类(它的子类)可能是sun.net.TelnetOutputStream或者sun.net.smtp.SmtpPrintStream 。。。。 你不清楚这个out到底指的是什么(实际上也不用去清楚),但是你通过OutputStreamwrint(byte[] data)方法,却可以向另外一端写入数据。(这就是面向对象的神奇的地方之一了,这个out表示“现在有一个OutputStream可以用了,你快用吧,其它的你不用管了“)。

       (这里另外值得注意的是抽象类 URLConnection,它代表应用程序和 URL 之间的通信链接。这里你本身不知道这个con到底是个什么样的连接,http?ftp?或者指向的是一个本地jar?根据构造器的参数u返回实际的处理通信链接的具体子类,这个con也可以这么认为现在返回一个连接了,你管它是什么连接呢,反正用吧

      

我觉得可以把程序和外部资源想象成2个点,你要使用外部资源,就要知道那个外部资源(URL)的点在那里,你就用URLConnection这把枪去射击那个资源点(URL),射中后会有根线(con)连接在程序和资源(URL)上面,然后你就用在这根线上铺设(getOutputStream())一个管道,铺设成功后就返回一个管道(out),你就对着管道抽取那资源,或者顺着管道往资源处加送程序的资源。(这段话纯属个人想象)

 

       The java.io.OutputStream class declares the three basic methods you need to write bytes of data onto a stream. It also has methods for closing and flushing streams:

 void

close()
          
关闭此输出流并释放与此流有关的所有系统资源。

 void

flush()
          
刷新此输出流并强制写出所有缓冲的输出字节。

 void

write(byte[] b)
          
b.length 个字节从指定的字节数组写入此输出流。

 void

write(byte[] b, int off, int len)
          
将指定字节数组中从偏移量 off 开始的 len 个字节写入此输出流。

abstract  void

write(int b)
          
将指定的字节写入此输出流。

 

 

       java.io.InputStream is the abstract superclass for all input streams. It declares the three basic methods needed to read bytes of data from a stream. It also has methods for closing streams, checking how many bytes of data are available to be read, skipping over input, marking a position in a stream and resetting back to that position, and determining whether marking and resetting are supported.

 int

available()
          
返回此输入流方法的下一个调用方可以不受阻塞地从此输入流读取(或跳过)的字节数。

 void

close()
          
关闭此输入流并释放与该流关联的所有系统资源。  PS:输入流可能占用非常稀有的资源,如文件句柄或网络端口号,所以使用完了一定要关闭)

 void

mark(int readlimit)
          
在此输入流中标记当前的位置。                  PS:一般只能有一个标记,设置第二个标记为消除第一个标记)

 boolean

markSupported()
          
测试此输入流是否支持 mark reset 方法。   PS:在使用mark方法前先用此方法测试输入流是否支持mark

abstract  int

read()
          
从输入流读取下一个数据字节。

 int

read(byte[] b)
          
从输入流中读取一定数量的字节并将其存储在缓冲区数组 b 中。

 int

read(byte[] b, int off, int len)
          
将输入流中最多 len 个数据字节读入字节数组。

 void

reset()
          
将此流重新定位到对此输入流最后调用 mark 方法时的位置。

 long

skip(long n)
          
跳过和放弃此输入流中的 n 个数据字节。

 

一些简单的代码框架:

关闭输入流

// Initialize this to null to keep the compiler from complaining

// about uninitialized variables

InputStream in = null;

try {

  URL u = new URL("http://www.msf.org/");

  in = u.openStream( );

  // Read from the stream...

}

catch (IOException ex) {

  System.err.println(ex);

}

finally {

  if (in != null) {

    try {

      in.close( );

    }

    catch (IOException ex) {

      System.err.println(ex);

    }

  }

}

PS:finally里关闭输入流是个不错的方法。

关闭输出流

// Initialize this to null to keep the compiler from complaining

// about uninitialized variables

OutputStream out = null;

try {

  out = new FileOutputStream("numbers.dat");

  // Write to the stream...

}

catch (IOException ex) {

  System.err.println(ex);

}

finally {

  if (out != null) {

    try {

      out.close( );

    }

    catch (IOException ex) {

      System.err.println(ex);

    }

  }

}

An Efficient Stream Copier

import java.io.*;

public class StreamCopier {

  public static void main(String[] args) {

    try {

      copy(System.in, System.out);

    }

    catch (IOException ex) {

      System.err.println(ex);

    }

  }

  public static void copy(InputStream in, OutputStream out)

   throws IOException {

    byte[] buffer = new byte[1024];

    while (true) {

      int bytesRead = in.read(buffer);

      if (bytesRead == -1) break;

      out.write(buffer, 0, bytesRead);

    }

  }

}

 

PS:下面一篇文章我会谈下所谓我理解的I/O的第二个层次 知道各个具体的子类的区别,即知道各种架设的管道的材质和适用的范围。

原创粉丝点击