猴子哥哥的博客

学习交流

InputStream、FileInputStream之read()、skip()可靠性加强

        有经验java程序猿都知道,java中对输入流的读取往往是不可靠的,例如inputStream.read(buffer,0,1024);并不是每次都能读取到1024个字节,而是最多能够读取1024个字节,jdk源码如下:

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;
    }

可以看到当出现一次IO异常则该次读取结束,提高了性能的同时,其可靠性打了折扣,通常都会使用while循环来从读过的索引位置继续读取,但是有的时候我们要求不使用while循环而就要读到我们需要的字节数,下面通过设置可靠性系数,以牺牲发生IO异常时的性能来提高其可靠性,对jdk源码稍加改造如下:


import java.io.IOException;
import java.io.InputStream;


/**
 * 改善InputStream自带方法的不可靠缺陷
 * @author zhangh-ag
 *
 */
public class InputStreamUtil {

private static native int readBytes(byte b[], int off, int len) throws IOException;

/**
* 改善InputStream自带read方法不可靠的问题
* @param oInputStream 要读取的流
* @param b 接收数组
* @param off 从数组的哪个位置
* @param len 读的长度
* @param reReadMaxCount 可靠系数(默认同原生InputStream)
* @return
*/
public static int read(InputStream oInputStream, byte b[], int off, int len, int reReadMaxCount) 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;
        }

if (reReadMaxCount <= 0) {
reReadMaxCount = 1;
}



        int c = -1;
try {
c = oInputStream.read();
} catch (IOException e) {
e.printStackTrace();
}
        if (c == -1) {
            return -1;
        }
        b[off] = (byte)c;


        int i = 1;
        int nCount = 1;
    while (i < len && nCount <= reReadMaxCount) {
    try {
c = oInputStream.read();
if (c == -1) {
               break;
           }
           b[off + i] = (byte)c;
           i++;
} catch (IOException e) {
nCount++;
}
    }
   
    if (nCount > reReadMaxCount && reReadMaxCount != 1) {
    throw new IOException();
    }
   
        return i;
}

/**
* 改善InputStream自带skip方法不可靠的问题
* @param oInputStream 要读取的流
* @param n 要跳过的长度
* @param reReadMaxCount  可靠系数(默认同原生InputStream)
* @return
* @throws IOException
*/
public static long skip(InputStream oInputStream, long n, int reReadMaxCount) throws IOException {
long remaining = n;
        int nr = 0;


        if (n <= 0) {
            return 0;
        }
        
        int nCount = 1;
        if (reReadMaxCount <= 0) {
        reReadMaxCount = 1;
        }


        int size = (int)remaining;
        byte[] skipBuffer = new byte[size];
        while (remaining > 0 && nCount <= reReadMaxCount) {
            try {
nr = oInputStream.read(skipBuffer, nr, (int)Math.min(size, remaining));
} catch (IOException e) {
nCount++;
}
            if (nr < 0) {
                break;
            }
            remaining -= nr;
        }
        
        if (nCount > reReadMaxCount && reReadMaxCount != 1) {
    throw new IOException();
    }


        return n - remaining;
}


}




package com.glodon.util;


import java.io.FileInputStream;
import java.io.IOException;


/**
 * 改善FileInputStream自带方法的不可靠缺陷
 * @author zhangh-ag
 *
 */
public class FileInputStreamUtil {

/**
* 改善FileInputStream自带read方法不可靠的问题
* @param oInputStream 要读取的流
* @param b 接收数组
* @param off 从数组的哪个位置
* @param len 读的长度
* @param reReadMaxCount 可靠系数(默认同原生InputStream)
* @return
*/
public static int read(FileInputStream oFileInputStream, byte b[], int off, int len, int reReadMaxCount) 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;
        }

if (reReadMaxCount <= 0) {
reReadMaxCount = 1;
}

        int nCount = 1;
        int nTempLength = 0;
int bytesRead = 0;

while (bytesRead < len && nTempLength != -1) {
try {
nTempLength = oFileInputStream.read(b, off + bytesRead, len - bytesRead);
} catch (IOException e) {
nCount ++;
if (nCount > reReadMaxCount) {
throw e;
}
}

if (nTempLength != -1) {
bytesRead += nTempLength;
}
}

        return bytesRead;
}

/**
* 改善FileInputStream自带skip方法不可靠的问题
* @param oInputStream 要读取的流
* @param n 要跳过的长度
* @param reReadMaxCount  可靠系数(默认同原生InputStream)
* @return
* @throws IOException
*/
public static long skip(FileInputStream oFileInputStream, long n, int reReadMaxCount) throws IOException {
if (n <= 0) {
            return 0;
        }

if (reReadMaxCount <= 0) {
reReadMaxCount = 1;
}

int nCount = 1;
long remain = n;
long refactSkipLength = 0;

while (remain > 0 && refactSkipLength != -1) {
try {
refactSkipLength = oFileInputStream.skip(remain);
} catch (IOException e) {
nCount ++;
if (nCount > reReadMaxCount) {
throw e;
}
}
if (refactSkipLength != -1) {
remain -= refactSkipLength;
}
}

return n- remain;
}


}

阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_21033663/article/details/51541298
个人分类: java
上一篇JMeter测试Java
下一篇javaweb文件下载方式总结
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭