java学习笔记(二) InputStream

来源:互联网 发布:网络打击赌博最新新闻 编辑:程序博客网 时间:2024/06/04 00:24

这个类的命名空间结构如下:

java.io.InputStream

它的函数结构如下:


public abstract int read() throws IOException
public int read(byte[] data) throws IOException
public int read(byte[] data, int offset, int length) throws IOException
public long skip(long n) throws IOException
public int available() throws IOException
public void close() throws IOException
public synchronized void mark(int readlimit)
public synchronized void reset() throws IOException
public boolean markSupported()


继续我们具体的讲每个函数的具体作用

Ps :这个类中出现了一个synchronized关键字,这个关键字是在实现多线程时很有用的一个关键字。

在多线程的情况下,由于同一进程中多个线程共享一片存储区域,在带来方便的同时,也带来了访问冲突的问题。

1.成员变量一般情况下都通过private限制访问权限,所以仅仅讨论synchronized修饰成员方法的情况,如果用关键字修饰了这个成员函数,那么在这个类实例中会有一把锁,只有当当前线程获取都这个实例的锁的时候,才能调用,否则当前线程会被阻塞,等待正在执行的有锁的线程结束之后获取到锁,然后执行,有效的避免了实例中同一成员变量被使用造成的冲突。

2.因为很可能一个函数中只有一小段代码需要调用同一个成员变量,如果将函数声明为synchronized会导致线程不必要的阻塞,所以我们就可以利用synchronized做一些效率更加高的解决访问冲突问题的方法:

 synchronized 块:通过 synchronized关键字来声明synchronized 块。语法如下:synchronized(syncObject) {//允许访问控制-的代码}synchronized 块是这样一个代码块,其中的代码必须获得对象 syncObject (如前所述,可以是类实例或类)的锁方能执行,具体机制同前所述。由于可以针对任意代码块,且可任意指定上锁的对象,故灵活性较高。 
补充玩这部分内容,我们就来具体讲一下这个类的具体函数的功能:

-----------------------------------------read()函数---------------------------------------------------------

public abstract int read ( ) throws IOException

这个函数实际上是读了一个字节,但是返回是这个字节构成的有符号整数,也就是-128-127的范围,我们可以通过强制类型转换,得到这个字节,当read读到了输入流的末尾的时候会返回-1,而不会抛出IOException,我们可以用它来作为读入是否结束的标志,因为有时候读入有时候很消耗时间,所以我们一般都单独开一个线程来进行读入操作,避免浪费系统资源。

read()是抽象函数,所以InputStream是抽象类,抽象类是不能实例化的,所以InputStream类型的变量只能够声明,而实例化的时候,必须实例化为它的非抽象的子类

----------------------------------------read( byte[] data )函数---------------------------------------------

public int read ( byte[] data ) throws IOException

public int read ( byte[] data , int offset , int length ) throws IOException

在介绍这两个函数之前,首先我们要明白他们存在的意义,I/o常常是程序开发中效率提升的瓶颈,因为读写速度包括从硬盘上读写要比从内存读写慢上百倍,从网络获取和从用户获取更慢,远远不及CPU的执行速度,导致效率提升收到限制,那么我们只能尽可能少的减少读写次数,所以可以先将要写内容写在数组上,利用缓存存储,然后在一并写入内存硬盘,往往能获得更高的效率

那么接下来具体介绍以下他们的作用,他们的返回值是读入的字节数,读入时会一直读,知道读入结束或者数组已满。这是第一个函数

第二个函数因为后两个参数的存在,可能导致数组越界,那么会抛出异常ArrayIndexOutOfBoundsException,其他的没有什么区别

-----------------------------------------avaliable()函数-------------------------------------------------------

public int avaliable () throws IOException

这个函数的作用是返回当前输入流能够不受阻塞的跳过或者读入最大的字节数,所以说我们在读入的时候可以利用这个函数初始化数组大小,但是如果在多次读入的时候,这样做就浪费了资源,一般情况下我们需要声明一个较大的数组,然后多次复用。

我们要了解一点,在java.io.InputStream这个抽象类当中,avaliable这个函数的实现是直接返回0,在它子类当中是存在一些子类没有覆盖这个函数的,那么有的时候我们在编程的过程中利用到了多态,也就是我们不知道底层inputstream到底有没有覆盖这个函数,所以我们不能确定我们会不会比读到avaliable()更多的数据而不会阻塞,所以我们可以将读入操作放入一个独立的线程当中,这样读入的阻塞就不会影响我们程序其他部分的执行。

--------------------------------------------skip()函数------------------------------------------------------------

public long skip(long bytesToSkip) throws IOException

这个函数的作用是在读入的过程跳过输出流当中的一些字节,参数给定了需要跳过的字节数,返回值返回的是实际跳过的字节,因为很可能实际跳过的字节会少于给定的参数的值,如果跳完之后遇到了读入结束标志,那么返回值返回-1,在跳过的过程的效率是比读入要快,如果把当前的输出流看成一个文件,因为它只是挪动指向当前文件的光标。

-------------------------------------------close()函数-----------------------------------------------------------

public void close() throws IOException

这个函数作用是关闭当前的输入流,且释放与其相关的资源。

不是所有的输入流都需要关闭,但是操作文件的输入流和从网络链接的输入流在操作完之后一般都要释放资源。如果一个输入流被关闭后,再进行读入操作,那么会抛出IOException.

------------------------------------------标记和反复-------------------------------------------------------------

有时候我们在读入的时候,对于< , << , <= ,我们再不读入<之后的符号之前,使不能判断当前的符号是什么。然而再有时读入完的值还需要退回输入流,那么标记输入流中的位置和重置到标记时的状态时就具有意义了。

但不是所有的inputstream都支持这一操作:

public synchronized void mark(int readLimit)
public synchronized void reset() throws IOException
public boolean markSupported()

markSupported函数是用来判断当前的输出流是否支持标记和重置的操作,如果支持,返回true,否则返回false

如果当前inputStream不支持标记返回,那么reset()就会返回IOException,mark函数什么操作也不做。如果当前的输入流是支持标记的,那么我们进行mark的时候会有一个参数,这个参数给出的是这个标记有效的最远的距离,然后每次调用reset就会回复到标记的状态。每次只要进行了新的标记,那么之前的标记都会被清除。BufferedInputStream和ByteArrayInputStream是一直支持标记的。







0 0
原创粉丝点击