我将类打成jar包将资源也放到jar包中的res目录下.
我用方式一读取文件能够正常把整个文件读入数组 b 中
方式一:
                InputStream is = this.getClass().getResourceAsStream("/res/a.jpg");
                byte[] b = new byte[is.available()];
for(;is.available()>0;i++){
b[i] = (byte)is.read();
}
                ImagIcon image = new ImageIcon(b);
用方式二读取文件只能将文件的前一部分读入数组 b 中导致创建ImageIcon时出错
方式二:
                InputStream is = this.getClass().getResourceAsStream("/res/a.jpg");
                byte[] b = new byte[is.available()];
is.read(b);
                ImagIcon image = new ImageIcon(b);我看到有人说不能用getResourceAsStream()方法读取jar包中的数据不知道这种说法正确吗?当然用这种方式一和这个 ImageIcon image = new ImageIcon(this.getClass().getResource("/res/a.png"));能够正常运行.有没有人遇到从jar包中读取资源的问题?
方式二为什么只能读取前一部分数据到数组中呢?

解决方案 »

  1.   

    倒是碰到过 读一个比较长的文本文件,总是有后面一部分 丢掉了!后来是 用 字符流读取,解决了这个问题!
    你这个问题,getResourceAsStream()方法 倒是没碰到过!有空 测试一下!
    关于JAR,读取应该问题不大,但不知道能不能通过程序 往JAR里添加内容!
      

  2.   

    向jar里添加东西就可以按zip包来处理吧?
      

  3.   

    InputStream.read(byte[]b)
    从输入流中读取一定数量的字节并将其存储在缓冲区数组 b 中,所以不是一次就读买整个数组b,通常需要循环来(正如你方法一)直到文件尾
      

  4.   

    is.available()
    返回此输入流方法的下一个调用方可以不受阻塞地从此输入流读取(或跳过)的字节数。这个方法不一定返回流所包含的所有字节,可能只是一部分,其实流在读取的过程中是不能获取到大小的.要正确读取全部的字节应该用循环读取,直到读取不到值为止
      

  5.   

    jar包也是个压缩包,可以先研究研究压缩文件在拿图片
      

  6.   

                            InputStream is = this.getClass().getResourceAsStream("/res/a.jpg");
    System.out.println("文件大小:"+is.available());
    byte[] b = new byte[is.available()];
    int i = 0;
    for(;is.available()>0;i++){
    int m = is.read();
    b[i] = (byte) m;
    }
    System.out.println("用For循环读取字节数为: "+i);

    is = this.getClass().getResourceAsStream("/res/a.jpg");
    System.out.println("文件大小:"+is.available());
    b = new byte[is.available()];
    i = is.read(b);
    System.out.println("用read共读取字节数为: "+i);
    加入了输出大家看一下如果不打jar包直接运行输出为:
    文件大小:27446
    用For循环读取字节数为: 27446
    文件大小:27446
    用read共读取字节数为: 27446打成jar包 通过java -jar 运行输出为:
    文件大小:27446
    用For循环读取字节数为: 27446
    文件大小:27446
    用read共读取字节数为: 8497所以这个不是is.available()的问题.查看了InputStream的api和源码都没弄明白这个问题.看这个源码也是一个一个读的呀?
     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;
        }
      

  7.   

    getResourceAsStream()是可以的。。quartz里面读取quartz.properties就是这么读取的嘛。。
      

  8.   

    这个不是is.available() 的问题了,看我12楼的.
      

  9.   

    我比较同意7楼的看法,is.available() ......
      

  10.   

    我写的那个//估计是这里有异常抛出  这个函数是Java源代码不是我写的.这个也可以试试.
      

  11.   

    根据12楼,肯定和压缩有关:在导出jar/zip包的时候是不是用个压缩选项?如果不勾选这个选项,导出后再读呢?jar文件实际大小是多少? 解压后大小是多少?但是,两种方式,代码展开来都一样的啊!不通啊,不通
      

  12.   

    打成jar包和不打jar包运行获得的文件的大小是一样的.就是打成jar包后用read(byte []) 方法读出来的是文件的一部分.
      

  13.   

    jlable 说得有点道理,7楼的只是猜测而已
      

  14.   

    is.available() 
    返回此输入流方法的下一个调用方可以不受阻塞地从此输入流读取(或跳过)的字节数。 这个方法不一定返回流所包含的所有字节,可能只是一部分,其实流在读取的过程中是不能获取到大小的.要正确读取全部的字节应该用循环读取,直到读取不到值为止
      

  15.   

    available()寫明:
    Returns an estimate of the number of bytes that can be read (or skipped over) from this input stream without blocking by the next invocation of a method for this input stream.
    不是其值不是文件的大小
    而inputstream中的read()方法都是盡量方法,不保證是會一次讀滿整個buf的,你給出的源代碼就是證明
      

  16.   

    is.available()我真的不记得这个代表里面数据的长度,这个应该是已经准备好的数据,而不是总数据量,否则如果你读取一个100G的文件,难道你要分配100G的数组啊?那还叫Stream吗?所以应该有一点,读一点,所以第一个循环是正确的,不过还是有点....
    byte[] bs = new byte[1024];
    int len;
    while((len = is.read(bs))!=-1){
      ....我更推荐这样读取Stream的数据,自己控制缓冲区
      

  17.   

    现在不是在讨论is.available()方法了 这个我不用了,现在是在讨论1、我用for循环一个一个byte读能读完整个文件,像这样
                  for(;is.available()>0;i++){
                    int m = is.read();
                    b[i] = (byte) m;
                }
    2、根据我发的read(byte[],int,int)的源代码
       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; 
        } 
    这里面也是用循环读取的,所以我调用这个方法应该返回和我自己用for循环读取一样的结果.
    但是返回的比我用for循环读取的要少请看下面的例子 我把大家有争议的available()方法去了.
                            InputStream is = this.getClass().getResourceAsStream("/res/a.jpg");
    System.out.println("文件大小/is.available():"+is.available());
    int length = 30000;

    byte[] b = new byte[length];
    int i = 0;
    for(;is.available()>0;i++){
    int m = is.read();
    b[i] = (byte) m;
    }
    System.out.println("用For循环读取字节数为: "+i);

    System.out.println("--------用read(byte[])方法读取-------------------");
    is = this.getClass().getResourceAsStream("/res/a.jpg");
    b = new byte[length];
    i = is.read(b);
    System.out.println("用read共读取字节数为: "+i);


    System.out.println("--------用read(byte[],int,int)方法读取-----------");
    is = this.getClass().getResourceAsStream("/res/a.jpg");
    BufferedInputStream bis = new BufferedInputStream(is); b = new byte[length];
    i = bis.read(b,0,b.length);
    System.out.println("用read(b,int,int)共读取字节数为: "+i);
     
    这个不打jar包输出的结果为:文件大小/is.available():27446
    用For循环读取字节数为: 27446
    --------用read(byte[])方法读取-------------------
    用read共读取字节数为: 27446
    --------用read(byte[],int,int)方法读取-----------
    用read(b,int,int)共读取字节数为: 27446打成jar包后运行输出的结果为:文件大小/is.available():27446
    用For循环读取字节数为: 27446
    --------用read(byte[])方法读取-------------------
    用read共读取字节数为: 8497
    --------用read(byte[],int,int)方法读取-----------
    用read(b,int,int)共读取字节数为: 27446看这个结果奇怪吧!!!read(byte[]) 调用的就是 read(byte[],int,int) 而我自己调用返回的结果却不同?
    各位再关注一下.
      

  18.   

    for(;is.available()>0;i++){
    你为何还在用这个方法,我无语你应该用返回值判断是否结束,而不是依赖于 available至于为什么?自己去看API的说明吧。if (c == -1) { 
                break; 
            } 这是jdk里面判断是否读取结束的方法,你自己看
      

  19.   


    for(;is.available()>0;i++){ 这个只是一个例子当时随便写的 我只是把后面两种方法的available方法去掉了.我改成这样:
    int i= 0;
    int c = -1;
    while((c = is.read())!=-1){
     b[i++] = (byte)c;
    }后面的结果也不对呀?
    InputStream is = this.getClass().getResourceAsStream("/res/a.jpg");
    System.out.println("文件大小/is.available():"+is.available());
    int length = 30000;

    byte[] b = new byte[length];
    int i = 0;
    int c = -1;
    while((c = is.read())!=-1){  //只是例子没有优化.
     b[i++] = (byte)c;
    }
    System.out.println("用while循环读取字节数为: "+i);

                //文件大小/is.available():27446
                //用while循环读取字节数为: 27446

    System.out.println("\n--------用read(byte[])方法读取-------------------");
    is = this.getClass().getResourceAsStream("/res/a.jpg");
    //-------------------重点看这里!!!!!----------------
    b = new byte[length];
    i = is.read(b);
    System.out.println("用read共读取字节数为: "+i); //--------用read(byte[])方法读取-------------------
    //用read共读取字节数为: 8497
    System.out.println("\n--------用read(byte[],int,int)方法读取-----------");
    is = this.getClass().getResourceAsStream("/res/a.jpg");
    BufferedInputStream bis = new BufferedInputStream(is);
    //-------------------重点看这里!!!!!----------------
    b = new byte[length];
    i = bis.read(b,0,b.length);
    System.out.println("用read(b,int,int)共读取字节数为: "+i);  //--------用read(byte[],int,int)方法读取-----------
     //用read(b,int,int)共读取字节数为: 27446

    重点看后面两个例子的输出read(byte[]) 方法是调用的return read(b, 0, b.length)这个但是这两个方法的输出为什么不同?
    一个输出的是
    --------用read(byte[])方法读取-------------------
    用read共读取字节数为: 8497
    另一个输出的是--------用read(byte[],int,int)方法读取-----------
    用read(b,int,int)共读取字节数为: 27446

    不用再关注available了 呵呵.
      

  20.   

    郁闷,不能删自己的帖子,上一个回复(51楼)写错了.请大家忽略! byte[] b = new byte[length];
    int i = 0;
    int c = -1;
    while((c = is.read())!=-1){//不考虑性能等其它事情.
     b[i++] = (byte)c;
    }
    System.out.println("用while循环读取字节数为: "+i);
    //文件大小/is.available():27446
    //用while循环读取字节数为: 27446 System.out.println("\n--------用read(byte[])方法读取-------------------");
    is = this.getClass().getResourceAsStream("/res/a.jpg");
    b = new byte[length];
    i = is.read(b);
    System.out.println("用read共读取字节数为: "+i);
    //--------用read(byte[])方法读取-------------------
    //用read共读取字节数为: 8497while循环和read(byte[])方法内部类似吧?
    为什么while可以读取的27446,而read(byte[]) 只可以读取8497
    不用再关注available了 呵呵.
      

  21.   

    试验了多个文件
    发现InputStream.read(byte[]) 就是有问题.
    但是不知道是那里的问题.
      

  22.   

    public int read(byte b[], int off, int len) throws IOException 方法的JAVADOC说得很清楚:Reads up to len  bytes of data from the input stream into
    an array of bytes.  An attempt is made to read as many as
    len  bytes, but a smaller number may be read.
    The number of bytes actually read is returned as an integer.它没有保证读得跟你要求的len一样长
    它只不过尝试attempt 读得跟len一样长
    你还是得关注实际读的长度actually read
      

  23.   

    lz,返回的len只要不是-1,就说明没有读完,这个read的方法没有保证一定可以读完。
    你的情况是读到中途的时候就出现IO异常了。该方法也说了,建议子类提供此方法更为有效的实现,
    所以不建议直接来用这个方法。