我有一段java httpjava下载代码的代码,但是我很多地方读不懂,帮我谢谢注释

使用java实现http多线程断点下载文件&二&
下载工具我想没有几个人不会用的吧,前段时间比较无聊,花了点时间用java写了个简单的http多线程下载程序,我实现的这个http下载工具功能很简单,就是一个多线程以及一个断点恢复,当然下载是必不可少的,需要的朋友可以参考下
下载工具我想没有几个人不会用的吧,前段时间比较无聊,花了点时间用java写了个简单的http多线程下载程序,纯粹是无聊才写的,只实现了几个简单的功能,而且也没写界面,今天正好也是一个无聊日,就拿来写篇文章,班门弄斧一下,觉得好给个掌声,不好也不要喷,谢谢!
我实现的这个http下载工具功能很简单,就是一个多线程以及一个断点恢复,当然下载是必不可少的。那么大概先整理一下要做的事情:
1、连接资源服务器,获取资源信息,创建文件
2、切分资源,多线程下载
3、断点恢复功能
4、下载速率统计
大概就这几点吧,那么首先要做的就是连接资源并获取资源信息,我这里使用了JavaSE自带的URLConnection进行资源连接,大致代码如下:
String urlStr = “/download/xxx”; //资源地址,随便写的
URL url = new URL(urlStr); //创建URL
URLConnection con = url.openConnection(); //建立连接
contentLen = con.getContentLength(); //获得资源长度
File file = new File(filename); //根据filename创建一个下载文件,也会是我们最终下载所得的文件
很简单吧,没错就是这么简单,第一步做完了,那么接下来要做第二步,切分资源,实现多线程。在上一步我们已经获得了资源的长度contentLen,那么如何根据这个对资源进行切分呢?假如我们要运行十个线程,那么我们就先把contentLen处以10,获得每块的大小,然后在分别创建十个线程,每个线程负责其中一块的写入,这就需要利用到RandomAccessFile这个类了,这个类提供了对文件的随机访问,可以指定向文件中的某一个位置进行写入操作,大致代码如下:
long subLen = contentLen / threadQ //获取每块的大小
//创建十个线程,并启动线程
for (int i = 0; i & threadQ i++) {
DLThread thread = new DLThread(this, i + 1, subLen * i, subLen * (i + 1) - 1); //创建线程
dlThreads[i] =
QSEngine.pool.execute(dlThreads[i]); //把线程交给线程池进行管理
在这里使用到了DLThread这个类,我们先来看看这个类的构造方法的定义:
public DLThread(DLTask dlTask, int id, long startPos, long endPos)
第一个参数为一个DLTask,这个类就代表一个下载任务,里面主要保存这一个下载任务的信息,包括下载资源名,本地文件名等等的信息。第二个参数就是一个标示线程的id,如果有10个线程,那么这个id就是从1到10,第三个参数startPos代表该线程从文件的哪个地方开始写入,最后一个参数endPos代表写到哪里就结束。
我们再来看看,一个线程启动后,具体如何去下载,请看run方法:
public void run() {
System.out.println("线程" + id + "启动");
BufferedInputStream bis = //创建一个buff
RandomAccessFile fos =
byte[] buf = new byte[BUFFER_SIZE]; //缓冲区大小
URLConnection con =
con = url.openConnection(); //创建连接,这里会为每个线程都创建一个连接
con.setAllowUserInteraction(true);
if (isNewThread) {
con.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos);//设置获取资源数据的范围,从startPos到endPos
fos = new RandomAccessFile(file, "rw"); //创建RandomAccessFile
fos.seek(startPos); //从startPos开始
con.setRequestProperty("Range", "bytes=" + curPos + "-" + endPos);
fos = new RandomAccessFile(dlTask.getFile(), "rw");
fos.seek(curPos);
//下面一段向根据文件写入数据,curPos为当前写入的未知,这里会判断是否小于endPos,
//如果超过endPos就代表该线程已经执行完毕
bis = new BufferedInputStream(con.getInputStream());
while (curPos & endPos) {
int len = bis.read(buf, 0, BUFFER_SIZE);
if (len == -1) {
fos.write(buf, 0, len);
curPos = curPos +
if (curPos & endPos) {
readByte += len - (curPos - endPos) + 1; //获取正确读取的字节数
readByte +=
System.out.println("线程" + id + "已经下载完毕。");
this.finished =
bis.close();
fos.close();
} catch (IOException ex) {
ex.printStackTrace();
throw new RuntimeException(ex);
上面的代码就是根据startPos和endPos对文件机型写操作,每个线程都有自己独立的一个资源块,从startPos到endPos。上面的方式就是线程下载的核心,多线程搞定后,接下来就是实现断点恢复的功能,其实断点恢复无非就是记录下每个线程完成到哪个未知,在这里我就是使用curPos进行的记录,大家在上面的代码就应该可以看到,我会记录下每个线程的curPos,然后在线程重新启动的时候,就把curPos当成是startPos,而endPost则不变即可,大家有没注意到run方法里有一段这样的代码:
if (isNewThread) { //判断是否断点,如果true,代表是一个新的下载线程,而不是断点恢复
con.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos);//设置获取资源数据的范围,从startPos到endPos
fos = new RandomAccessFile(file, "rw"); //创建RandomAccessFile
fos.seek(startPos); //从startPos开始
con.setRequestProperty("Range", "bytes=" + curPos + "-" + endPos);//使用curPos替代startPos,其他都和新创建一个是一样的。
fos = new RandomAccessFile(dlTask.getFile(), "rw");
fos.seek(curPos);
上面就是断点恢复的做法了,和新创建一个线程没什么不同,只是startPos不一样罢了,其他都一样,不过仅仅有这个还不够,因为如果程序关闭的话,这些信息又是如何保存呢?例如文件名啊,每个线程的curPos啊等等,大家在使用下载软件的时候,相信都会发现在软件没下载完的时候,在目录下会有两个临时文件,而其中一个就是用来保存下载任务的信息的,如果没有这些信息,程序是不知道该如何恢复下载进度的。而我这里又如何实现的呢?我这个人比较懒,又不想再创建一个文件来保存信息,然后自己又要读取信息创建对象,那太麻烦了,所以我想到了java提供序列化机制,我的想法就是直接把整个DLTask的对象序列化到硬盘上,上面说过DLTask这个类就是用来保存每个任务的信息的,所以我只要在需要恢复的时候,反序列化这个对象,就可以很容易的实现了断点功能,我们来看看这个对象保存的信息:
public class DLTask extends Thread implements Serializable {
private static final long serialVersionUID = 276024L;
private final static int MAX_DLTHREAD_QUT = 10; //最大下载线程数量
* 下载临时文件后缀,下载完成后将自动被删除
public final static String FILE_POSTFIX = ".tmp";
private URL
private int L
private int threadQ //下载线程数量,用户可定制
private int contentL //下载文件长度
private long completedT //当前下载完成总数
private int costT //下载时间计数,记录下载耗费的时间
private String curP //下载百分比
private boolean isNewT //是否新建下载任务,可能是断点续传任务
private DLThread[] dlT //保存当前任务的线程
transient private DLL //当前任务的监听器,用于即时获取相关下载信息
如上代码,这个对象实现了Serializable接口,保存了任务的所有信息,还包括有每个线程对象dlThreads,这样子就可以很容易做到断点的恢复了,让我重新写一个文件保存这些信息,然后在恢复的时候再根据这些信息创建一个对象,那简直是要我的命。这里创建了一个方法,用于断点恢复用:
private void resumeTask() {
listener = new DLListener(this);
file = new File(filename);
for (int i = 0; i & threadQ i++) {
dlThreads[i].setDlTask(this);
QSEngine.pool.execute(dlThreads[i]);
QSEngine.pool.execute(listener);
实际上就是减少了先连接资源,然后进行切分资源的代码,因为这些信息已经都被保存在DLTask的对象下了。
看到上面的代码,不知道大家注意到有一个对象DLListener没有,这个对象实际上就是用于监听整个任务的信息的,这里我主要用于两个目的,一个是定时的对DLTask进行序列化,保存任务信息,用于断点恢复,一个就是进行下载速率的统计,平均多长时间进行一个统计。我们先来看下它的代码,这个类也是一个单独的线程:
public void run() {
int i = 0;
BigDecimal completeTot = //完成的百分比
long start = System.currentTimeMillis(); //当前时间,用于记录开始统计时间
long end =
while (!dlTask.isComplete()) { //整个任务是否完成,没有完成则继续循环
String percent = dlTask.getCurPercent(); //获取当前的完成百分数
completeTot = new BigDecimal(dlTask.getCompletedTot()); //获取当前完成的总字节数
//获得当前时间,然后与start时间比较,如果不一样,利用当前完成的总数除以所使用的时间,获得一个平均下载速度
end = System.currentTimeMillis();
if (end - start != 0) {
BigDecimal pos = new BigDecimal(((end - start) / 1000) * 1024);
System.out.println("Speed :"
+ completeTot
.divide(pos, 0, BigDecimal.ROUND_HALF_EVEN)
+ "k/s " + percent + "% completed. ");
recoder.record(); //将任务信息记录到硬盘
sleep(3000);
} catch (InterruptedException ex) {
ex.printStackTrace();
throw new RuntimeException(ex);
//以下是下载完成后打印整个下载任务的信息
int costTime =+ (int)((System.currentTimeMillis() - start) / 1000);
dlTask.setCostTime(costTime);
String time = QSDownUtils.changeSecToHMS(costTime);
dlTask.getFile().renameTo(new File(dlTask.getFilename()));
System.out.println("Download finished. " + time);
这个方法中的recoder.record()方法的调用就是用于序列化任务对象,其他的代码均为统计信息用的,具体可看注释,record该方法的代码如下:
public void record() {
ObjectOutputStream out =
out = new ObjectOutputStream(new FileOutputStream(dlTask.getFilename() + ".tsk"));
out.writeObject(dlTask);
out.close();
} catch (IOException ex) {
ex.printStackTrace();
throw new RuntimeException(ex);
} finally {
out.close();
} catch (IOException ex) {
ex.printStackTrace();
throw new RuntimeException(ex);
到这里,大致的代码都完成了,不过以上的代码都是部分片段,只是作为一个参考给大家看下,而且由于本人水平有限,代码很多地方都没有经过过多的考虑,没有经过优化,仅仅只是自娱自乐,所以可能有很多地方都写的很烂,这个程序也缺乏很多功能,连界面都没有,所以整个程序的代码就不上传了,免得丢人,呵呵。希望对有兴趣的朋友尽到一点帮助吧。
Copyright (C) , All Rights Reserved.
版权所有 闽ICP备号
processed in 0.035 (s). 10 q(s)不懂JAVA,今天追查一个钓鱼网站代码的时候发现了一段,求高手鉴【java吧】_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:635,768贴子:
不懂JAVA,今天追查一个钓鱼网站代码的时候发现了一段,求高手鉴收藏
RT圈红的地方我发现有一段 www shouji com
是不是这段代码伪装成163的登录页面截取帐号密码之后提交给该网站?请大神解答
java-亚马逊819店庆,一站购全球,全品类齐放价,钜惠就在眼前!亚马逊819店庆,正品低价,送货上门,货到付款!
代码如下class div
ico href span
target _blank item ft logo dialogBox shadow ipt
hd copy style
nbsp label verSelect bg type btn title inner input rc ul error display none name iframe link src 163 img checkbox hidden for indexLogin h3 ext selected net tab tabindex SSL form alt width onclick mimg frameforlogin 126 yeah mailver wraper 127 top right oprt http shouji com placeholder password pwdInput button text rmbUser url2 bd h2 panel chkSSL left bottom gif allSSL userNameIpt list main position mailApp extText footer height theme png about blank mask h1 header page hidefocus html value 11px tab163Link body user idInputLine 2px index autocomplete off domain domainText NetEase tab126Link mainHd tabyeahLink idPlaceholder pass pwdInputLine errorAlert
tabshoujiLink errorArr btnSubmit email login submit pwdPlaceholder capsLockHint options arrow 87 margin 56px mid tt errorTitle errorDetail detail LoginTitle lnkWhySSL help hdMobExtLink why relative forGetPassword divError loginFootTipsVer 2012 ftVerSelLink now ftVerSelLinkTxt ftDarr darr loginFootTips loginFootTipsRight frmLogin verSelectUl styleConf method post styleConf7 styleConf6 verSelectTick tick loginForm arr locat expansion onSubmit return copyright 740px errorInfo sptln
KX_IMG knet submitForm info httploginframe new overflow border https ssl mail httpsEnable absolute frameborder scrolling no idInput account preview_popup username ntes_logo preview_popup_close savalogin close simpleContent preview_popup_cont impt preview_popup_submit savelogin&.split(& &),
登录百度帐号推荐应用查看: 635|回复: 2
请把下列一段java代码加上注释: 谢谢哈
阅读权限70
结帖率: (14/21)
& && && &public static ClientRecvObject updateUserInfo(Context p1, TianyaUserBo p2, User p3) {
& && &&&&url&.end(&userStand/updateUserInfo&);
& && &&&String &cstr& = p2.getSex() + p2.getBirthday() + p2.getProvince() + p2.getCity() + p2.getAboutMe() + UserEncryptUtil.getUserCheckString();
& && &&&&cstr& = MD5Util.MD5(&cstr&);
& && &&&Hashunknown_type &params& = new Hashunknown_type();
& && &&&&params&.put(&sex&, p2.getSex());
& && &&&&params&.put(&birthday&, p2.getBirthday());
& && &&&&params&.put(&province&, p2.getProvince());
& && &&&&params&.put(&city&, p2.getCity());
& && &&&&params&.put(&describe&, p2.getAboutMe());
& && &&&&params&.put(&cstr&, &cstr&);
& && &&&return TyClientDataUtils.DataFromServer(p1, &url&.toString(), p3.getCookie(), &params&, 0x0);
[e=1]public static ClientRecvObject updateUserInfo(Context p1, TianyaUserBo p2, User p3) {
//向url添加参数
url.append("userStand/updateUserInfo");
//User p3 相当于一个自定义类型的对象,获取几个属性,相加到一起
String cstr = p2.getSex() + p2.getBirthday() + p2.getProvince() + p2.getCity() + p2.getAboutMe() + UserEncryptUtil.getUserCheckString();
//MD5工具类加密User的一些信息
cstr = MD5U ...
回答提醒:如果本帖被关闭无法回复,您有更好的答案帮助楼主解决,请发表至
可获得加分喔。友情提醒:本版被采纳的主题可在
帖子申请荣誉值,获得 1点 荣誉值,荣誉值可兑换终身vip用户组哦。快捷通道: →
阅读权限90
签到天数: 5 天结帖率: (1/1)
&&public static ClientRecvObject updateUserInfo (Context p1, TianyaUserBo p2, User p3) {//向url添加参数url.append (&userStand/updateUserInfo&);//User p3 相当于一个自定义类型的对象,获取几个属性,相加到一起String cstr = p2.getSex () + p2.getBirthday () + p2.getProvince () + p2.getCity () + p2.getAboutMe () + UserEncryptUtil.getUserCheckString ();//MD5工具类加密User的一些信息cstr = MD5Util.MD5 (cstr);//这又是一个类Hashunknown_type params = new Hashunknown_type ();//应该是继承了Map之类的集合 获得User的每个参数,放到params里面params.put (&sex&, p2.getSex ());params.put (&birthday&, p2.getBirthday ());params.put (&province&, p2.getProvince ());params.put (&city&, p2.getCity ());params.put (&describe&, p2.getAboutMe ());//加密的这个也放进去params.put (&cstr&, cstr);//这应该是一个工具类,post提交的return TyClientDataUtils.postDataFromServer (p1, url.toString (), p3.getCookie (), params, 0x0);}public static ClientRecvObject updateUserInfo(Context p1, TianyaUserBo p2, User p3) {
& & & & //向url添加参数
& & & & url.append(&userStand/updateUserInfo&);
& & & & //User p3 相当于一个自定义类型的对象,获取几个属性,相加到一起
& & & & String cstr = p2.getSex() + p2.getBirthday() + p2.getProvince() + p2.getCity() + p2.getAboutMe() + UserEncryptUtil.getUserCheckString();
& & & & //MD5工具类加密User的一些信息
& & & & cstr = MD5Util.MD5(cstr);
& & & & //这又是一个类
& & & & Hashunknown_type params = new Hashunknown_type();
& & & & //应该是继承了Map之类的集合 获得User的每个参数,放到params里面
& & & & params.put(&sex&, p2.getSex());
& & & & params.put(&birthday&, p2.getBirthday());
& & & & params.put(&province&, p2.getProvince());
& & & & params.put(&city&, p2.getCity());
& & & & params.put(&describe&, p2.getAboutMe());
& & & & //加密的这个也放进去
& & & & params.put(&cstr&, cstr);
& & & & //这应该是一个工具类,post提交的
& & & & return TyClientDataUtils.postDataFromServer(p1, url.toString(), p3.getCookie(), params, 0x0);
热心帮助他人,荣誉+1,希望继续努力(*^__^*) 嘻嘻!
您可以选择打赏方式支持他
阅读权限200
结帖率: (3/3)
楼上V5,但我估计楼主还是看不懂!还不如直接说是怎么加密的!要哪些参数等
您可以选择打赏方式支持他
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
揭阳精易科技有限公司申明:我公司所有的培训课程版权归精易所有,任何人以任何方式翻录、盗版、破解本站培训课程,我们必将通过法律途径解决!
公司简介:揭阳市揭东区精易科技有限公司致力于易语言教学培训/易语言学习交流社区的建设与软件开发,多年来为中小企业编写过许许多多各式软件,并把多年积累的开发经验逐步录制成视频课程供学员学习,让学员全面系统化学习易语言编程,少走弯路,减少对相关技术的研究与摸索时间,从而加快了学习进度!
防范网络诈骗,远离网络犯罪
违法和不良信息举报电话,企业QQ: ,邮箱:@
Powered by
粤公网安备 25}

我要回帖

更多关于 java下载代码 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信