`

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();
	}
}



分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics