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());
}
}
}
n = 0;
st = 0;
System.arraycopy(b, 0, buff, st, n);
以上是我从你代码中找到的变量和方法,全是0和null没有值你怎么调用copy方法
楼主你的while循环中没有关于越界的判断,也就是说,你总是假设你的缓冲区能装下整个文件。
这显然是不现实的。你应该加入清理缓冲区的操作。
你的debug信息看起来已经很清楚了,告诉你超过了缓冲区的大小。
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);
}
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的括号中进行填充。
在while中给n赋值你是在和我搞笑吗,这个是判定语句,到你这就成了赋值语句,你可真牛b,回去好好看看buffer这个地方的书吧
麻烦您看清楚:
n = buffer.read(b, 0, 1366) 赋值
作为一个表达式,它也是有值的,它的值,就是buffer.read(b, 0, 1366)的返回值,也就是n。
所以说有了这样的写法;
(n = buffer.read(b, 0, 1366)) != -1
在赋值的同时做判断。
流读取常用的格式,明白?
如果还不服气,单独开贴让大家评理。
另外,我觉得你很没素质,真的。
con.setRequestProperty("Range", "bytes="+start+"-"+end);
请求从start开始到end(Bybe)段文件内容
调试时缓冲区每次刚刚好多出一Byte
最后查出是end没有减一
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的括号中进行填充你敲下代码看看能出来值不,能出来你在说没用的