关闭

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

标签: read不可靠skip不可靠InputStream改善FileInputStream改善
1901人阅读 评论(0) 收藏 举报
分类:

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


}

0
0
查看评论

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

最近写一个网络下载软件,需要使用java.IO.InputStream.skip(long n) 方法,它的作用是从输入流中跳过 n 个字节,比如 inputStream.skip(12),就是从inputStream中读最近写一个网络下载软件,需要使用取数据时,跳过前 12 个字节,从第13个字节...
  • u010156024
  • u010156024
  • 2015-04-27 21:39
  • 2818

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

解读: java.io.InputStream.skip(long n):跳过和放弃此输入流中的 n 个数据字节,返回的是跳过的实际字节数。如果skip方法的返回值小于要跳过得字节数,则说明有异常发生,此时需要对异常情况进行处理。 ¨案例:   fileI...
  • zxcvg
  • zxcvg
  • 2011-08-09 18:51
  • 5488

InputStream.skip方法的思考

在java.io.InputStream类中定义了skip这个方法。在API中的描述如下:skippublic long skip(long n) throws IOException Skips over and discards n bytes...
  • GSYzhu
  • GSYzhu
  • 2012-10-23 12:42
  • 15954

Java IO(二) 之 InputStream

源码均以JDK1.8作为参考前言: InputStream实现了两个接口Closeable和AutoCloseable: Closeable:JDK1.5中引入,Closeable接口中只有一个close()方法的定义: public void close() throws IOExce...
  • securitit
  • securitit
  • 2015-07-26 00:08
  • 1185

被readLine()折腾了一把

虽然写IO方面的程序不多,但BufferedReader/BufferedInputStream倒是用过好几次的,原因是:它有一个很特别的方法:readLine(),使用起来特别方便,每次读回来的都是一行,省了很多手动拼接buffer的琐碎;它比较高效,相对于一个字符/字节地读取、转换、返回来说,它...
  • swingline
  • swingline
  • 2010-03-08 19:26
  • 87058

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

有经验java程序猿都知道,java中对输入流的读取往往是不可靠的,例如inputStream.read(buffer,0,1024);并不是每次都能读取到1024个字节,而是最多能够读取1024个字节,jdk源码如下: public int read(byte b[], int off, int ...
  • qq_21033663
  • qq_21033663
  • 2016-05-30 21:34
  • 1901

InputStream方法详解

字节输入流的基础类InputStream和OutputStream有许多相同的地方,也有许多不同点,需注意区分。 概要 与OutputStream相比,这个抽象类定义的方法要多一些。读入数据有些时候的确比较麻烦。读入数据的时候,需要判断数据源是否有数据,是否结束等等一些情况,相对复杂。这个抽象类...
  • bingduanlbd
  • bingduanlbd
  • 2013-01-30 17:25
  • 12893

InputStream read()方法详解

在Java7中,InputStream被定义为一个抽象类,相应的,该类下的read()方法也是一个抽象方法,这也就意味着必须有一个类继承InputStream并且实现这个read方法。 查阅Java7 API,我们可以看到,在InputStream中定义了三个重载的read()方法: 但是在...
  • u010276761
  • u010276761
  • 2016-09-28 19:03
  • 11136

InputStream.skip方法的思考

http://blog.csdn.net/gsyzhu/article/details/8102286 在java.io.InputStream类中定义了skip这个方法。在API中的描述如下: skip public long skip(long n...
  • luofeixiongsix
  • luofeixiongsix
  • 2015-10-22 19:21
  • 336

java io -- InputStream

上篇文章java io-流简单介绍了流的概念,本文我们就关注于字节流。 从java字节流说起,java的字节流有两种:输入流和输出流,我这里只分析输入流,输出流与输入流类似,只是方向相反。 输入流,顾名思义,就是我们输入我们程序的字节流,也就是如果我们的程序需要输入时,我们从流中读取。 输入流...
  • zhao123h
  • zhao123h
  • 2016-10-15 23:12
  • 769
    个人资料
    • 访问:203521次
    • 积分:3180
    • 等级:
    • 排名:第12814名
    • 原创:118篇
    • 转载:53篇
    • 译文:2篇
    • 评论:11条
    最新评论