while ((n = buffer.read(b, 0, 1366)) != -1) {
                    try{
                        System.arraycopy(b, 0, buff, st, n);//出错
                    } catch (Exception ee) {//13987
                        System.out.println(Thread.currentThread() + "st:" + st + ",n:" + n);
                        System.out.println((1366*1024 -st)+"  "+ee.toString());
                    }
                    synchronized (ITHIS) {
                        down_len += n;
                    }
                    st += n;
                }
/*错误
Thread[Thread-1,5,main]st:1397486,n:1299
1298 java.lang.ArrayIndexOutOfBoundsException
Thread[Thread-2,5,main]st:1398300,n:485
484 java.lang.ArrayIndexOutOfBoundsException
*/
//全代码import java.io.*;
import java.net.*;
import java.util.logging.*;public class downfile {    final downfile ITHIS = this;    public static void main(String[] args) {
        downfile d = new downfile();
        d.from_url = "http://202.103.221.29:81/bk/UploadFiles/2007-3/37572051.mp3";
        d.to_file = "d:/1.mp3";
        d.start();
    }
    String from_url;
    String to_file;
    /**
     * 文件总长度
     */
    long file_length;
    int ids;
    /**
     * 是否已下载,第1366*1024Byte(1.33MB)为一单位
     */
    boolean[] is_downs;
    ToolDownload[] threan_down;
    long down_len;
    long down_all_len;    public synchronized int getId() {
        for (int i = 0; i < ids; i++) {
            if (!is_downs[i]) {
                is_downs[i] = true;
                return i;
            }
        }
        return -1;
    }    /**
     * 开始任务
     */
    void start() {
        try {
            URLConnection con = new URL(from_url).openConnection();
            file_length = con.getContentLength();
            ids = (int) (file_length / (1366 * 1024));
            if (file_length % (1366 * 1024) > 0) {
                ids++;
            }
            System.out.println("ids" + ids);
            is_downs = new boolean[ids];
            if (ids > 10) {
                threan_down = new ToolDownload[10];
                for (int i = 0; i < 10; i++) {
                    threan_down[i] = new ToolDownload();
                }
            } else {
                threan_down = new ToolDownload[ids];
                for (int i = 0; i < ids; i++) {
                    threan_down[i] = new ToolDownload();
                }
            }
            new Thread(new Runnable() {                long time = System.currentTimeMillis() / 1000;                public void run() {
                    while (ITHIS.file_length > ITHIS.down_all_len) {
                        synchronized (ITHIS) {
                            System.out.println((ITHIS.down_len / 1024 / 1.0) + "kb/s");
                            ITHIS.down_all_len += ITHIS.down_len;
                            ITHIS.down_len = 0;
                            try {
                                Thread.sleep(1000);
                            } catch (InterruptedException ex) {
                            }
                        }
                    }
                    System.out.println("文件下载完毕");
                    System.out.println("下载所用总时间: " + (System.currentTimeMillis() / 1000 - time) + "s");
                }
            }).start();
            for (ToolDownload td : threan_down) {
                td.down(getId());
            }
        } catch (IOException ex) {
            Logger.getLogger(downfile.class.getName()).log(Level.SEVERE, null, ex);
        }
    }    class ToolDownload extends Thread {        URL url = null;
        URLConnection con = null;
        RandomAccessFile rand;
        int id;
        byte[] b = new byte[1366];
        byte[] buff = new byte[1366 * 1024];
        int st;
        int n;
        boolean is_start = false;        ToolDownload() {
            try {
                url = new URL(from_url);
                con = url.openConnection();
                con.setAllowUserInteraction(true);
                rand = new RandomAccessFile(new File(to_file), "rw");
            } catch (IOException ex) {
                Logger.getLogger(downfile.class.getName()).log(Level.SEVERE, null, ex);
            }
        }        /**
         * 下载第id段文件
         */
        void down(final int id) {
            if (id < 0) {
                return;
            }
            this.id = id;
            this.start();
        }        @Override
        public void run() {
            synchronized (ITHIS) {
                if (is_start) {
                    return;
                }
                is_start = true;
            }
            try {
                System.out.println("线程" + this.getName() + "启动...");
                con.setRequestProperty("Range", "bytes=" + (id * 1366 * 1024) + "-" + ((id + 1) * 1366 * 1024 > file_length ? file_length : (id + 1) * 1366 * 1024));
                BufferedInputStream buffer = new BufferedInputStream(con.getInputStream());
                n = 0;
                st = 0;
                while ((n = buffer.read(b, 0, 1366)) != -1) {
                    try{
                        System.arraycopy(b, 0, buff, st, n);
                    } catch (Exception ee) {//13987
                        System.out.println(Thread.currentThread() + "st:" + st + ",n:" + n);
                        System.out.println((1366*1024 -st)+"  "+ee.toString());
                    }
                    synchronized (ITHIS) {
                        down_len += n;
                    }
                    st += n;
                }
                rand.seek(id * 1366 * 1024);
                rand.write(buff);
                System.out.println("线程" + this.getName() + "下载完毕");
                buffer.close();
            } catch (Exception ee) {
                ee.printStackTrace();
            }
            is_start = false;
            down(ITHIS.getId());
        }
    }
}

解决方案 »

  1.   

    byte[] b = new byte[1366];
    n = 0;
    st = 0;
    System.arraycopy(b, 0, buff, st, n);
    以上是我从你代码中找到的变量和方法,全是0和null没有值你怎么调用copy方法
      

  2.   

    2楼你肯定没仔细看代码。
    楼主你的while循环中没有关于越界的判断,也就是说,你总是假设你的缓冲区能装下整个文件。
    这显然是不现实的。你应该加入清理缓冲区的操作。
    你的debug信息看起来已经很清楚了,告诉你超过了缓冲区的大小。
      

  3.   

    System.arraycopy(b, 0, buff, st, n);//很明显,如果st+n>buff.length,那就数组越界了
    if (st+n > buff.length) {
        if (st < buff.length) {
            System.arraycopy(b, 0, buff, st, buff.length-st);
        }
        System.out.printf("overflow:%d\n", st+n-buff.length);
    } else {
        System.arraycopy(b, 0, buff, st, buff.length-st);
    }
      

  4.   

                    while ((n = buffer.read(b, 0, 1366)) != -1) {
                        try{
                            System.arraycopy(b, 0, buff, st, n);
                        } catch (Exception ee) {//13987
                            System.out.println(Thread.currentThread() + "st:" + st + ",n:" + n);
                            System.out.println((1366*1024 -st)+"  "+ee.toString());
                        }
                        synchronized (ITHIS) {
                            down_len += n;
                        }
                        st += n;
                    }
    在while中给n赋值,每次循环体结束后重置st。
    buff是缓冲区,在while的括号中进行填充。
      

  5.   

    while ((n = buffer.read(b, 0, 1366)) != -1)
    在while中给n赋值
    你是在和我搞笑吗,这个是判定语句,到你这就成了赋值语句,你可真牛b,回去好好看看buffer这个地方的书吧
      

  6.   

    哇,好牛B也。
    麻烦您看清楚:
    n = buffer.read(b, 0, 1366) 赋值
    作为一个表达式,它也是有值的,它的值,就是buffer.read(b, 0, 1366)的返回值,也就是n。
    所以说有了这样的写法;
    (n = buffer.read(b, 0, 1366)) != -1
    在赋值的同时做判断。
    流读取常用的格式,明白?
    如果还不服气,单独开贴让大家评理。
    另外,我觉得你很没素质,真的。
      

  7.   

    解决了,谢谢大家了
    con.setRequestProperty("Range", "bytes="+start+"-"+end);
    请求从start开始到end(Bybe)段文件内容
    调试时缓冲区每次刚刚好多出一Byte
    最后查出是end没有减一
      

  8.   

    没你牛b 你去开帖子吧,我什么也没说就弄个我没素质,caonima才叫美素质,什么人,说你2局就给我弄个没素质,你有素质你怎么不闭嘴哪
      

  9.   

    狗b我见得多了 ,没见过sb,不知道是哪个狗生下来的狗崽,一下生除了骂人不会别的,你有种就去开贴吧,看看是谁只会叫唤,我是骂你了还是caonima了,你真个鸡巴德行,除了说别人没素质你还会caonima吧,和你爸一起cao是不
      

  10.   

    在你bb之前你先把下面的这几个值给我解释下
    b,buff, st
    然后告诉我他们的值,再告诉我通过n = buffer.read(b, 0, 1366)你能得到以上3个哪个的值,
    然后你再看看我发的帖子说的是什么问题,是问你给n赋值还是以上3个,我只能给你一个解释,
    虽然你说n = buffer.read(b, 0, 1366)是给n赋值我不反对,但是(n = buffer.read(b, 0, 1366)) != -1
    是进行判断你觉得那?而且我也没问你n的值,我问
    引用 3 楼 bayougeng 的回复:2楼你肯定没仔细看代码。
    楼主你的while循环中没有关于越界的判断,也就是说,你总是假设你的缓冲区能装下整个文件。
    这显然是不现实的。你应该加入清理缓冲区的操作。
    你的debug信息看起来已经很清楚了,告诉你超过了缓冲区的大小。你仔细看了,哪你告诉我他们的值都是什么
    你就给我回答while ((n = buffer.read(b, 0, 1366)) != -1) {
    try{
    System.arraycopy(b, 0, buff, st, n);
    } catch (Exception ee) {//13987
    System.out.println(Thread.currentThread() + "st:" + st + ",n:" + n);
    System.out.println((1366*1024 -st)+" "+ee.toString());
    }
    synchronized (ITHIS) {
    down_len += n;
    }
    st += n;
    }
    在 while中给n赋值,每次循环体结束后重置st。
    buff是缓冲区,在while的括号中进行填充
    你敲下代码看看能出来值不,能出来你在说没用的