多线程文件下载出错

若鱼1919 山东科技大学 开发工程师  2009-02-22 09:20:28
本来想做一个多线程文件下载的程序,就是想把源文件分割,不同的线程读取不同的部分,写到目标文件中,结果:当源文件的地址是网络地址的时候出错,而是本地地址的时候是正确的,哪位大侠帮忙看看怎么回事?
import java.net.*;
import java.util.*;
import java.io.*;
public class MyDownLoad{//多线程下载文件

public static void main(String args[]){//
final int DOWN_THREAD_NUM = 4;
final String OUT_FILE_NAME = "down.rar";
InputStream[] isArr = new InputStream[DOWN_THREAD_NUM];
RandomAccessFile[] outArr = new RandomAccessFile[DOWN_THREAD_NUM];
try
{
//创建一个URL对象

URL url = new URL("http://localhost/picture/MyPictures.rar");
//以此URL对象打开第一个输入流
InputStream in= url.openStream();
long fileLen = getFileLength(url);
System.out.println("网络资源的大小" + fileLen);
/*
File f=new File("F:/media/film/MyPictures.rar");
long fileLen = f.length();
InputStream in= new FileInputStream(f);
System.out.println("本地资源的大小" + fileLen);
//当从网络上下载的时候是失败的,但是从本机是成功的,不知道什么原因?
*/
//以输出文件名创建第一个RandomAccessFile输出流
RandomAccessFile rf= new RandomAccessFile(OUT_FILE_NAME , "rw");
//创建一个与下载资源相同大小的空文件
rf.setLength(fileLen);
for (int i = 0 ; i < fileLen ; i++ )
{
rf.writeByte(1) ;
}

//每线程应该下载的字节数
long numPerThred = fileLen/DOWN_THREAD_NUM;
//整个下载资源整除后剩下的余数 取模
long left = fileLen % DOWN_THREAD_NUM;

System.out.println("numPerThred="+numPerThred+",left="+left);
int i=0;
for (i = 0 ; i < DOWN_THREAD_NUM; i++)
{
//以URL打开多个输入流
isArr[i] = url.openStream();
//isArr[i] =new FileInputStream(f);
//以指定输出文件创建多个RandomAccessFile对象
outArr[i] = new RandomAccessFile(OUT_FILE_NAME , "rw");
//每个线程负责下载一定的numPerThred个字节
Thread t=new Thread(new DownLoadThread(i * numPerThred,(i + 1) * numPerThred,isArr[i],outArr[i]));
t.start();
}
//另外一个线程下载指定left个字节
if(left>=1)new Thread(new DownLoadThread(i * numPerThred, i * numPerThred + left,in,rf)).start();
else{in.close();rf.close();}
}catch (Exception ex){ex.printStackTrace();}

}

private static long getFileLength(URL url) throws Exception
{
long length = 0;
//打开该URL对应的URLConnection。
URLConnection con = url.openConnection();
//获取连接URL资源的长度
return con.getContentLength();
}
}
class DownLoadThread implements Runnable
{
//定义字节数组(取水的竹筒)的长度
private final int BUFF_LEN = 1000;
//定义下载的起始点
private long start;
//定义下载的结束点
private long end;
//下载资源对应的输入流
private InputStream is;
//将下载到的字节输出到raf中
private RandomAccessFile raf ;
//构造器,传入输入流,输出流和下载起始点、结束点
public DownLoadThread(long start , long end
, InputStream is , RandomAccessFile raf)
{
//输出该线程负责下载的字节位置
//System.out.println(""+Thread.currentThread().getName()+":"+start + "---->" + end);
this.start = start;
this.end = end;
this.is = is;
this.raf = raf;
}
public void run()
{
System.out.println(""+Thread.currentThread().getName()+":"+start + "---->" + end);
try
{
is.skip(start);
raf.seek(start);
//定义读取输入流内容的的缓存数组(竹筒)
byte[] buff = new byte[BUFF_LEN];

//本线程负责下载资源的大小
long contentLen = end - start;

//实际读取的字节数
int hasRead = 0;

//定义最多需要读取几次就可以完成本线程的下载
long times = (contentLen+BUFF_LEN-1) / BUFF_LEN;

for (int i = 0; i < times ; i++)
{
hasRead = is.read(buff);
raf.write(buff , 0 , hasRead);
//如果读取的字节数小于0,则退出循环!
if (hasRead < 0) break;
}

}catch (Exception ex){ex.printStackTrace();}
//使用finally块来关闭当前线程的输入流、输出流
finally
{
try
{
if (is != null)
{
is.close();
}
if (raf != null)
{
raf.close();
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
}
...全文
69 点赞 收藏 1
写回复
1 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复

还没有回复,快来抢沙发~

相关推荐
发帖
Web 开发
创建于2007-09-28

8.0w+

社区成员

Java Web 开发
申请成为版主
帖子事件
创建了帖子
2009-02-22 09:20
社区公告
暂无公告