上篇文章总体介绍了一下Java-IO流的整体层次结构。本篇文章就具体对字节流的输入流(InputStream)和输出流(OutputStream)进行介绍。
输入流 InputStream:
InputStream类的层次结构
该类中的一些简单方法:
(1)read()方法:从输入流中读取数据的下一个字节,返回0-255范围内的int字节值,如果已经达到流末尾没有可用字节,则返回-1。
(2)read(byte[] b)方法:从输入流中读入一定长度的字节,并以整数的形式返回字节数。
(3)read(byte[] b,int off,int len)方法:从输入流中读取数据最多len个字节,并存储在缓存数组b中。
(4)mark(int readlimit)方法:在输入流的当前位置放置一个标记,readlimit参数告诉此输入流在标记位置失效之前允许读取的字节数。
(5)reset()方法:将输入指针返回到当前所做的标记处。
(6)skip(long n)方法:跳过输入流上的n个字节并返回实际跳过的字节数。
(7)markSupported()方法:如果当前流支持mark()/reset()操作就返回True。
(8)close方法:关闭输入流释放与该流关联的所有系统资源。
注意:并不是所有的InputStream类的子类都支持InputStream中定义的所有方法。
接下来看看其源码具体实现过程:
Demo:
import java.io.IOException;
public abstract class InputStreamDemo {
//缓存区字节数组最大值
private static final int MAX_SKIP_BUFFER_SIZE=2048;
//从输入流读取数据的下一个字节,以int返回
public abstract int read() throws IOException;
//从输入流读取数据的一定数量字节,并存储在缓存数组b中
public int read(byte b[]) throws IOException{
return read(b,0,b.length);
}
//从输入流中读取数据最多len个字节,并存储在缓存数组b中
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(); //调用read()方法
if(c==-1) //如果没有可读的字符
{
return -1;
}
b[off]=(byte)c;
int i=1;
/*
* 将读取的第一个字节存储在元素b[off]里面,下一个存储在b[off+1],依次读取
* 如果读取到最后没有字符可读break,
*/
try{
for(;i<len;i++)
{
c=read();
if(c==-1)
{
break;
}
b[off+i]=(byte)c;
}
}catch(IOException e)
{
}
return i;
}
//跳过输入流中数据的n个字节
public long skip(long n)throws IOException{
long remaining=n;
int nr;
if(n<=0)
{
return 0;
}
int size=(int)Math.min(MAX_SKIP_BUFFER_SIZE, remaining);
byte[] skipBuffer=new byte[size];
while(remaining>0)
{
nr=read(skipBuffer,0,(int)Math.min(size, remaining));
if(nr<0)
break;
remaining-=nr;
}
return n-remaining;
}
//在此输出流中标记当前位置
public synchronized void mark(int readlimit){}
//将此流重新定位到最后一次对此输入流调用mark方法时的位置
public synchronized void reset() throws IOException
{
throw new IOException("mark/reset not supported");
}
//测试此输入流是否直接mark和reset方法
public boolean markSupported()
{
return false;
}
//关闭输入流和释放资源
public void close()throws IOException{
}
}
具体代码中的synchronized的线程并发个人还需要去看看其他大牛的博客学习。
输出流 OutputStream
OutputStream类的层次结构
该类的方法:
(1)write(int b)方法:将指定的字节写入此输出流。
(2)write(byte[] b)方法:将b个字节从指定的byte数组写入此输出流。
(3)write(byte[] b,int off,int len)方法:将指定byte数组中从偏移量off开始的len个字节写入此输出流。
(4)flush方法:彻底完成输出并清空缓存区。
(5)close方法:关闭输出流。
注意:OutputStream类中的所有方法均返回void。
接下来看看其源码具体实现过程:
Demo:
import java.io.Closeable;
import java.io.Flushable;
import java.io.IOException;
public abstract class OutputStreamDemo implements Closeable,Flushable{
//将指定的字节写入输出流
public abstract void write(int b) throws IOException;
//将指定的byte数组的字节全部写入输出流
public void write(byte[] b) throws IOException
{
write(b,0,b.length);
}
//将指定的byte数组中从偏移量off开始的len个字节写入输出流
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{}
}
不难看出,OutputStream和InputStream是对应着看的。
其中字节输入输出流有很重要的几个方法:
其中abstract int read()和abstract void write(int b)是抽象方法,子类必须实现此方法,后面的两种read()和write()均调用了此抽象方法,可见read()和write()方法在传统的IO是多么重要。