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

原创 2016年05月30日 21:34:21

        有经验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;
}


}

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

InputStream.skip方法的思考

在java.io.InputStream类中定义了skip这个方法。在API中的描述如下:skippublic long skip(long n) throws IOExcepti...
  • GSYzhu
  • GSYzhu
  • 2012年10月23日 12:42
  • 14861

Java软件低级错误(十 八):忽略InputStream.skip()返回值的处理

解读: java.io.InputStream.skip(long n):跳过和放弃此输入流中的 n 个数据字节,返回的是跳过的实际字节数。如果skip方法的返回值小于要跳过得字节数,则说明有异常...
  • zxcvg
  • zxcvg
  • 2011年08月09日 18:51
  • 5112

Java.IO.InputStream.skip() 错误(跳过字节数和预想的不等)

最近写一个网络下载软件,需要使用java.IO.InputStream.skip(long n) 方法,它的作用是从输入流中跳过 n 个字节,比如 inputStream.skip(12),就是从in...

InputStream.skip方法的思考

http://blog.csdn.net/gsyzhu/article/details/8102286 在java.io.InputStream类中定义了skip这个方法。在API中的描...

FileInputStream的read方法

今天写android程序时,被这一句搞迷糊了:

FileInputStream 之read(byte [] b)方法

FileInputStream是InputStream的子类,由名称上就可以知道, FileInputStream主要就是从指定的File中读取资料至目的地。 FileOutputStream是...

Inputstream转换成String

一、InputstreamUtil.java package com.x.util; import java.io.BufferedReader; import java.io.ByteArrayO...

java的输入字节流 FileInputStream类

File类: 用于描述一个文件或者文件夹的。  通过File对象我们可以读取文件或者文件夹的属性数据,如果我们需要读取文件的内容数据,那么我们需要使用IO流技术。   IO流(Input O...
  • oguro
  • oguro
  • 2016年12月19日 09:14
  • 1222

java基本I/O系列--ByteArrayInputStream 介绍

转载自:http://www.cnblogs.com/skywang12345/p/io_01.html FYI ByteArrayInputStream 是字节数组输入流。它继承于InputS...

I/O流之进步认识、InputStream以及FileInputStream

File类: 用于描述一个文件或者文件夹的。 通过File对象,我们可以读取文件或者文件夹的属性数据,如果我们需要读取文件的内容数据,那么我们需要使用IO流技术。IO流(Input Output) ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:InputStream、FileInputStream之read()、skip()可靠性加强
举报原因:
原因补充:

(最多只允许输入30个字)