Java_io体系之InputStream、OutputStream简介、走进源码——03

Java_io体系之InputStream、OutputStream简介、走进源码——03


一:InputStream


1、       InputStream类简介:

InputStream:字节输入流、是所有字节输入流的父类、本身个抽象类、为字节输入流提供一个标准、和基本的方法及简单的实现、子类可以根据自己的特点进行重写和扩

展。InputStream中有一个抽象方法read()、是字节输入流的核心、要求子类必须实现此方法、此方法也是字节输入流的核心方法、


2、       InputStream 方法简介:


A:构造方法

本身是抽象类、无构造方法。

B:一般方法

	int avaliable();查看当前流中可供读取的字节数。
	
	void close();关闭当前流、释放所有与当前流有关的资源。
	
	synchronized void mark(int readlimit);标记当前流的读取的位子。
	
	boolean markSupport();查看当前流是否支持mark。
	
	abstract int read();读取当前流中的下一个字节、并以整数形式返回、若读取到文件结尾则返回-1。
	
	int read(byte[] b);将当前流中的字节读取到字节数组b中、返回实际读取的字节数
	
	int read(byte[] b, int off, int len);将当前流中的len个字节读取到从下标off开始存放的字节数组b中。
	
	synchronized reset();重置当前流的读取位置到最后一次调用mark方法标记的位置。
		
	long skip(long n);跳过(抛弃)当前流中n个字节。返回实际抛弃的字节数。


3、       InputStream源码分析:


/**
 * 所有字节输出流的父抽象类。提供字节输入流所共有的基本的读取方法。
 */
public abstract class InputStream implements Closeable {

    // skipBuffer的大小
    private static final int SKIP_BUFFER_SIZE = 2048;
    // 内置字节缓存数组、用于构建skip方法中临时存放抛弃的字节。
    private static byte[] skipBuffer;

    /**
     * 	抽象的方法 用于读取输入流中的下一个字节、由其实现类去重写。这也是流的关键方法、下面几个方法都是直接或者间接调用read()方法来实现。
     * @return 0 到 255 之间的整数。如果读到流的结尾则返回 -1 。
     */
    public abstract int read() throws IOException;

    /**
     *	从方法实现也可看出、他是不断调用read(byte[] b, 0, b.length)这个方法作为其方法体。
     * @param      作为一个缓存字节数组来存放从流中读取的字节。
     * @return     读取的字节总个数、如果读到结尾、则返回-1.
     */
    public int read(byte b[]) throws IOException {
    	return read(b, 0, b.length);
    }

    /**
     *	不断的调用read()方法来读取流中的字节、存放到  b 中。
     * @param  b 用来存放读取的字节的字节缓存数组、off 从b[off]开始放 、len 放len个
     * @return 返回读取的字节的总个数。
     */
    public int read(byte b[], int off, int len) throws IOException {
		if (b == null) {
		    throw new NullPointerException();
		} else if (off < 0 || len < 0 || len > b.length - off) {
		    throw new IndexOutOfBoundsException();
		} else if (len == 0) {
		    return 0;
		}
	
		int c = read();
		if (c == -1) {
		    return -1;
		}
		b[off] = (byte)c;
	
		int i = 1;
		try {
		    for (; i < len ; i++) {
			c = read();
			if (c == -1) {
			    break;
			}
			b[off + i] = (byte)c;
		    }
		} catch (IOException ee) {
		}
		return i;
    }

    /**
     * 返回跳过的字节数的个数。
     * 这里根本就看不出这个方法到底有什么实际的用途、但是当看到后面的子类实现类的方法体就知道了。
     * @param      n   我们想从从输入流中跳过的字节数
     * @return    实际跳过的字节数、因为有可能输入流中没有那么多有效字节被抛弃、此时则会跳过剩余所有字节、返回的字节数也就是跳之前剩余的字节数。
     */
    public long skip(long n) throws IOException {
    	//方法思想:实际抛弃的字节数  = 想要抛弃的字节数  - 剩余需要抛弃的字节数
    	
    	//记录还剩余多少字节要跳过。
		long remaining = n;
		
		//中间变量、记录每次读取的实际字节数
		int nr;
		//初始化默认大小的全局字节数组。
		if (skipBuffer == null)
		    skipBuffer = new byte[SKIP_BUFFER_SIZE];
		//创建临时的用于存放被读取的字节的字节数组、像垃圾桶、回收被跳过的字节、满了之后在读取就清空从新回收。
		byte[] localSkipBuffer = skipBuffer;
			
		if (n <= 0) {
		    return 0;
		}
		//次循环意义在于记录剩余需要抛弃的字节数
		//大条件、如果还有字节需要被跳过、也就是抛弃、没有则结束循环
		while (remaining > 0) {
			//记录此次实际读取的字节数、后面参数的意义在于防止出现IndexOutOfBoundsException异常。
			
		    nr = read(localSkipBuffer, 0,
			      (int) Math.min(SKIP_BUFFER_SIZE, remaining));
		    //如果读到输入流结尾、则结束循环。
		    if (nr < 0) {
		    	break;
		    }
		    //修改记录还要抛弃的字节数的值
		    remaining -= nr;
		}
		//将n减去还剩多少需要被抛弃的值就是实际抛弃的值
		return n - remaining;
    }

    /**
     * 返回输入流中可读取的有效的字节数、若子类提供此功能、则需要重新实现。
     */
    public int available() throws IOException {
    	return 0;
    }

    /**
     * 关闭流、释放所有与此流有关的资源。
     */
    public void close() throws IOException {}

    /**
     * 在输入流中标记当前位置、与reset()结合使用、
     * 若子类不提供此功能则调用此方法没有任何效果。
     * 若子类提供此功能、则需重新实现。
     */
    public synchronized void mark(int readlimit) {}

    /**
     * 与mark(int readlimit)结合使用、将此流定位到最后一次mark的位置、即调用reset之后、程序继续重mark的位置读取字节流。
     * 若子类不支持此方法、调用则会抛出异常、可事先调用下面的markSupported()来查看当前流是否支持此功能。
     */
    public synchronized void reset() throws IOException {
    	throw new IOException("mark/reset not supported");
    }

    /**
     * 查看当前流是否支持mark、默认是false、即如果实现类不重写此方法就意味着其不支持mark。
     */
    public boolean markSupported() {
    	return false;
    }
}
 
 

二:OutputStream

1、OutputStream简介:

       OutputStream:字节输出流、同InputStream意义相同、本身是一个抽象类、为所有字节输出流提供一个标准、和一些简单的方法及简单实现。其核心方法是一个抽象方法: write(byte b)要求子类必须实现此方法、不同功能的类对此方法的实现方式不

一样、一般情况下子类要重写其大多数方法、或者新增一些方法、用于满足更多的需要。

2、OutputStream 方法简介:

A:构造方法

本身是抽象类、无构造方法。

B:一般方法

	
	abstract void write(byte b);将一个字节写入到当前输出流管道中。

	void write(byte[] b);将字节数组b中所有字节写入到当前输出流管道中。

	void write(byte[] b, int off, int len);将字节数组b从下标off开始、len个字节写入当前输出流管道中

	void flush();flush当前流、将当前流中的所有数据冲刷到目的地中。

	void close();关闭当前流、释放与当前流有关的所有资源。


3、OutputStream源码分析:

public abstract class OutputStream implements Closeable, Flushable {
    /**
     *	将一个8位的字节写入到当前字节输出流中。其子类必须重写、实现此方法。
     */
    public abstract void write(int b) throws IOException;

    /**
     * 将字节数组中b.length个字节写入到当前输出流中。此方法相当与write(byte[] b, 0, b.length);因为其内部就是调用下面的方法。
     */
    public void write(byte b[]) throws IOException {
    	write(b, 0, b.length);
    }

    /**
     * 将一个字节数组中从下标off开始、len个字节写入到当前输出流中。不断调用write来实现的。
     */
    public void write(byte b[], int off, int len) throws IOException {
		if (b == null) {
		    throw new NullPointerException();
		} else if ((off < 0) || (off > b.length) || (len < 0) ||
			   ((off + len) > b.length) || ((off + len) < 0)) {
		    throw new IndexOutOfBoundsException();
		} else if (len == 0) {
		    return;
		}
		for (int i = 0 ; i < len ; i++) {
		    write(b[off + i]);
		}
    }

    /**
     * 将当前输出流中的所有残留数据刷新到目的地中去。
     */
    public void flush() throws IOException {}

    /**
     * 关闭当前输出流、释放所有与此流有关的资源。
     */
    public void close() throws IOException {}
}
 
  

更多IO内容:java_io 体系之目录


你可能感兴趣的:(java,Inputstream,OutputStream,IO流,ReaderWriter)