jdk6.0从入门到精通-----chapter7线程(3)多线程下载程序

主程序,获得欲下载文件的大小,根据其大小分配线程数量和下载的偏移量

package mulithreaddownload;

import java.net.URL;
import java.net.HttpURLConnection;
import java.io.File;
import java.io.RandomAccessFile;
import java.io.IOException;

public class DownloadManager {
static final long unitSize = 100 * 1024; // 分配给每个下载线程的字节数

public static void main(String[] args) throws IOException {
if (args.length != 2) {
System.out
.println("Usage java DownloadManager URL local_file_name");
return;
}
DownloadManager downloadManager = new DownloadManager();
downloadManager.doDownload(args[0], args[1]);
}

public void doDownload(String remoteFileUrl, String localFileName)
throws IOException {
long fileSize = this.getRemoteFileSize(remoteFileUrl);
this.createFile(localFileName, fileSize);
long threadCount = fileSize / unitSize;
System.out.println("共启动线程"
+ (fileSize % unitSize == 0 ? threadCount : threadCount + 1)
+ "个");
long offset = 0;
if (fileSize <= unitSize) // 如果远程文件尺寸小于等于unitSize
{
DownloadThread downloadThread = new DownloadThread(remoteFileUrl,
localFileName, offset, fileSize);
downloadThread.start();
} else // 如果远程文件尺寸大于unitSize
{
for (int i = 1; i <= threadCount; i++) {
DownloadThread downloadThread = new DownloadThread(
remoteFileUrl, localFileName, offset, unitSize);
downloadThread.start();
offset = offset + unitSize;
}
if (fileSize % unitSize != 0) // 如果不能整除,则需要再创建一个线程下载剩余字节
{
DownloadThread downloadThread = new DownloadThread(
remoteFileUrl, localFileName, offset, fileSize
- unitSize * threadCount);
downloadThread.start();
}
}
}

// 获取远程文件尺寸
private long getRemoteFileSize(String remoteFileUrl) throws IOException {
long result = 0;
HttpURLConnection httpConnection = (HttpURLConnection) new URL(
remoteFileUrl).openConnection();
httpConnection.setRequestMethod("HEAD");
for (int i = 1; i <= 10; i++) {
if (httpConnection.getHeaderFieldKey(i).equalsIgnoreCase(
"Content-Length")) {
result = Long.parseLong(httpConnection.getHeaderField(i));
break;
}
}
return result;
}

// 创建指定大小的文件
private void createFile(String fileName, long fileSize) throws IOException {
File newFile = new File(fileName);
RandomAccessFile raf = new RandomAccessFile(newFile, "rw");
raf.setLength(fileSize);
raf.close();
}
}


下载的具体实现有线程实现

package mulithreaddownload;

import java.net.URL;
import java.net.HttpURLConnection;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.RandomAccessFile;
import java.io.IOException;

public class DownloadThread extends Thread {
private String url = null; // 待下载的文件
private String file = null; // 本地存储路径
private long offset = 0; // 偏移量
private long length = 0; // 分配给本线程的下载字节数

public DownloadThread(String url, String file, long offset, long length) {
this.url = url;
this.file = file;
this.offset = offset;
this.length = length;
System.out.println("偏移量=" + offset + ";字节数=" + length);
}

public void run() {
try {
HttpURLConnection httpConnection = (HttpURLConnection) new URL(
this.url).openConnection();
httpConnection.setRequestMethod("GET");
httpConnection.setRequestProperty("RANGE", "bytes=" + this.offset
+ "-" + (this.offset + this.length - 1));
BufferedInputStream bis = new BufferedInputStream(httpConnection
.getInputStream());
byte[] buff = new byte[1024]; // 分段读取,防止内容泄露
int bytesRead;
while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
this.writeFile(this.file, this.offset, buff, bytesRead);
this.offset = this.offset + bytesRead;
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}

// 将字节数组以随机存取方式写入文件
// fileName是被写入的文件
// offset代表写入文件的位置偏移量
// bytes是待写入的字节数组
// realLength是实际需要写入的字节数(realLength<=bytes.length)
private void writeFile(String fileName, long offset, byte[] bytes,
int realLength) throws IOException {
File newFile = new File(fileName);
RandomAccessFile raf = new RandomAccessFile(newFile, "rw");
raf.seek(offset);
raf.write(bytes, 0, realLength);
raf.close();
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值