`
不夜的星辰
  • 浏览: 86747 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

android 单线程 多线程下载

阅读更多

单线程下载很简单,就是开启一个线程去下载资源再进行本地保存;

多线程下载是通过RandomAccessFile(随机文件读写操作类)来设置每个线程读取文件的起始点位置,起始点之间的长度即为该线程需要下载的文件大小

下载开始位置:线程id*每条线程下载的数据长度 = ?

下载结束位置:(线程id+1)*每条线程下载的数据长度-1=?

这样比如文件大小:size,线程数:threads,则每个线程的下载量:size/threads;但是这是整除的情况,如果考虑到不能整除的情况:则前threads-1个线程下载量为size/threads,最后一个线程的下载量:size/threads+size%threads

package file.down;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

import javax.security.auth.PrivateCredentialPermission;

import android.R.integer;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewDebug.FlagToString;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;

public class File_downActivity extends Activity {
	private Button but1,but2;
	private EditText etUrl;
	private ProgressBar bar1,bar2;
	private TextView tv1,tv2;
	private boolean flag = true;
	private int temp = 0;
	private int downLoadedSize = 0;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        etUrl = (EditText) findViewById(R.id.downloadUrl);
        
        but1 = (Button) findViewById(R.id.but1);
        but2 = (Button) findViewById(R.id.but2);
        
        bar1 = (ProgressBar) findViewById(R.id.downloadProgressBar1);
        bar2 = (ProgressBar) findViewById(R.id.downloadProgressBar2);
        
        tv1 = (TextView) findViewById(R.id.tv1);
        tv2 = (TextView) findViewById(R.id.tv2);
        
        
        //单线程下载
        but1.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				if(DownUtil.isExistSdCard()){
					if(DownUtil.checkNet(File_downActivity.this)){
						if(DownUtil.creatDir(DownUtil.path1)){
							thread.start();
						}
					}
				}
			}
		});
        //多线程下载
        but2.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				mulThread.start();
			}
		});
    }
    @Override
    protected void onDestroy() {
    	super.onDestroy();
    	DownUtil.downLoadSize = 0;
    }
    /**
     * 单线程下载
     */
    private Thread thread = new Thread(new Runnable() {
		
		@Override
		public void run() {
				
				DownUtil.fileDown1(etUrl.getText().toString(), DownUtil.savePath1, handler);
				bar1.setMax(DownUtil.fileSize);
		}
	});
    /**
     * 多线程下载(主线程类)
     */
    private Thread mulThread = new Thread(new Runnable() {
		private int blockSize,downLoadSizeMore;
		private int threadNum = 5;//线程数
		
		@Override
		public void run() {
//			MulDownThread[] threads = new MulDownThread[threadNum];
			try {
				URL url = new URL(etUrl.getText().toString());
				URLConnection connection = url.openConnection();
				DownUtil.fileSize2 = connection.getContentLength();
				if(DownUtil.fileSize2 <= 0){
					return;
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
			//计算每个线程下载的数据量
			blockSize = DownUtil.fileSize2 / threadNum;
			//解决整除后余下的数据量
			downLoadSizeMore = DownUtil.fileSize2 % threadNum;
			bar2.setMax(100);
			if(DownUtil.creatDir(DownUtil.path2)){
				
				File file = new File(DownUtil.savePath2 + "/" + etUrl.getText().toString().substring(etUrl.getText().toString().lastIndexOf("/") + 1));
				for(int i=0;i<threadNum;i++){
					if(i < threadNum - 1){
						
						//启动线程,分别下载文件
						MulDownThread thread = new MulDownThread(etUrl.getText().toString(), file, i*blockSize, (i + 1) * blockSize - 1,handler);
						thread.start();
					}else{//最后那个线程下载的文件长度要等于每个线程平均下载量加上整除后的余数
						MulDownThread thread = new MulDownThread(etUrl.getText().toString(), file, i*blockSize, (i + 1) * blockSize - 1 + downLoadSizeMore,handler);
						thread.start();
					}
//					//启动线程,分别下载文件
//					MulDownThread thread = new MulDownThread(etUrl.getText().toString(), file, i*blockSize, (i + 1) * blockSize -1);
//					thread.start();
//					handler.sendEmptyMessage(10);
				}
//				boolean finished = false;
//				while(!finished){
//					//先把整除的余数搞定
//					downLoadedSize = downLoadSizeMore;
//					finished = true;
//					for(int i = 0;i<threads.length;i++){
//						downLoadedSize += threads[i].downLoadSize;
//						if(!threads[i].isFinisthed){
//							finished = false;
//						}
//					}
//					handler.sendEmptyMessage(10);
//				}
			}
		}
	});
    private Handler handler = new Handler(){
    	public void handleMessage(android.os.Message msg) {
    		switch (msg.what) {
			case 0:
				tv1.setText("无法获取文件大小");
				break;
			case -1:
				tv1.setText("下载完成");
				bar1.setProgress(100);
				but1.setClickable(false);
			    break;

			case 1:
				but1.setClickable(false);
				int result = Double.valueOf(((Integer.parseInt(msg.obj.toString())*1.0 / DownUtil.fileSize * 100))).intValue();
				bar1.setProgress(result);
				tv1.setText(result + "%");
				break;
			case 2:
				tv1.setText("文件获取错误");
				break;
		    case 10://多线程下载更新进度条
		    	but2.setClickable(false);
		    	int result2 = (Double
						.valueOf((Integer.parseInt(msg.obj.toString()) * 1.0 / DownUtil.fileSize2 * 100)))
						.intValue();
		    	bar2.setProgress(result2);
		        if(result2 == 100){
		        	tv2.setText("下载完成");
		        }else{
		        	
		        	tv2.setText(result2 + "%");
		        }
		    	break;
			}
    	};
    };
}

 

package file.down;

import java.io.File;

import android.os.Handler;
/**
 * 线程类
 * @author Administrator
 *
 */
public class MulDownThread extends Thread {

	private String url;
	private File file;
	private int startPosition;
	private int endPosition;
	private Handler handler;
	
	
	public MulDownThread(String url,File file,int startPosition,int endPosition,Handler handler){
		this.url = url;
		this.file = file;
		this.startPosition = startPosition;
		this.endPosition = endPosition;
		this.handler = handler;
	}
	
	@Override
	public void run() {
		DownUtil.fileDown2(url, file, startPosition, endPosition,handler);
	}

	
	
}

 

package file.down;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

import android.R.integer;
import android.R.string;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

public class DownUtil {

	//单线程下载目录
	public static String path1 = "/down1/";
	public static String savePath1;
	//多线程下载目录
	public static String path2 = "/down2/";
	public static String savePath2;
	
	public static String fileName;
	public static int fileSize;
	public static int fileSize2;
	
	private static int curPosition;
	//已下载的文件大小
	public static int downLoadSize;
	//标示当前线程是否下载完成
	public static boolean finished = false;
	/**
	 * 判断sd卡是否存在
	 * Environment.MEDIA_MOUNTED 判断SD卡是否存在
	 * @return
	 */
	public static boolean isExistSdCard(){
		boolean flag = true;
		if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
			flag = false;
		}
		return flag;
	}
	/**
	 * 创建目录
	 * @param dir
	 * @return
	 */
	public static boolean creatDir(String dir){
		boolean flag = false;
		File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + dir);
		if(!file.exists()){
			file.mkdir();
			if(file.exists()){
				flag = true;
				savePath1 = file.getAbsolutePath();
				savePath2 = file.getAbsolutePath();
			}
		}else{
			flag = true;
			savePath1 = file.getAbsolutePath();
			savePath2 = file.getAbsolutePath();
		}
		return flag;
	}
	/**
	 * 检查网络是否可用
	 * @return
	 */
	public static boolean checkNet(Context context){
		boolean flag = false;
		ConnectivityManager manager = (ConnectivityManager) context.getSystemService(context.CONNECTIVITY_SERVICE);
		NetworkInfo wifi = manager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
		NetworkInfo mobile = manager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
		if(wifi.isConnectedOrConnecting() || mobile.isConnectedOrConnecting()){
			flag = true;
		}
		return flag;
	}
	/**
	 * 单线程文件下载
	 * @param url
	 * @param path
	 */
	public static void fileDown1(String url,String path,Handler handler) {
		Log.v("=path=", path+"=");
		Message message = new Message();
		if(!"".equals(url)){
			fileName = url.substring(url.lastIndexOf("/") + 1);
			InputStream inputStream = null;
			FileOutputStream outputStream = null;
			try {
				URL myuUrl = new URL(url);
				URLConnection connection = myuUrl.openConnection();
				connection.connect();
				inputStream = connection.getInputStream();
				fileSize = connection.getContentLength();
				Log.v("=fileSize=", DownUtil.fileSize+"=");
				if(fileSize <= 0){
					message.what = 0;
					handler.sendMessage(message);
					return;
				}else{
					outputStream = new FileOutputStream(path +"/"+ fileName);
					//存储文件
					byte buf[] = new byte[inputStream.available()];
					int len = 0;
					int temp = 0;
					Log.v("=available=", inputStream.available()+"=");
					while ((len = inputStream.read(buf)) != -1) {
						outputStream.write(buf, 0, len);
						temp += len;
						Message message2 = new Message();
						message2.what = 1;
						message2.obj = temp;//下载的百分比
						handler.sendMessage(message2);
					}
					Message msg = new Message();
					//通知下载完成
					msg.what = -1;
					handler.sendMessage(msg);
				}
			} catch (Exception e) {
				message.what = 2;
				handler.sendMessage(message);
				return;
			}finally{
				try {
					
					if(inputStream != null || outputStream != null){
						outputStream.close();
						inputStream.close();
					}
				} catch (Exception e2) {
				}
			}
		}
	}
	/**
	 * 多线程下载文件
	 * @param url
	 * @param path
	 * @param handler
	 */
	public static void fileDown2(String url,File file,int startPosition,int endPosition,Handler handler){
		URLConnection connection = null;
		InputStream inputStream = null;
		BufferedInputStream bis = null;
		RandomAccessFile raf = null;
		try {
			URL url2 = new URL(url);
			connection = url2.openConnection();
//			connection.connect();
			connection.setAllowUserInteraction(true);
			// 设置当前线程下载的起点,终点
			connection.setRequestProperty("Range", "bytes=" + startPosition + "-"
					+ endPosition);
			inputStream = connection.getInputStream();
			if(fileSize2 <= 0){
				return;
			}
			//对文件进行随机读写操作
			raf = new RandomAccessFile(file,"rw");
			//设置开始写文件的位置
			raf.seek(startPosition);
			bis = new BufferedInputStream(inputStream);
			//开始循环以流的形式读写文件
//			curPosition = startPosition;
			//每个线程需要读取文件的长度
//			int temp = endPosition - startPosition;
			byte[] buffer = new byte[1024];
			int length = 0;
			while ((length = inputStream.read(buffer)) != -1) {
				raf.write(buffer, 0, length);
				downLoadSize += length;
				Message message = new Message();
				message.what = 10;
				message.obj = downLoadSize;
				handler.sendMessage(message);
			}
//			while (curPosition < endPosition) {
//				int len = bis.read(buffer, 0, temp);
//				if(len == -1){
//					break;
//				}
//				Log.v("=len=", "="+len);
//				raf.write(buffer, 0, len);
//				curPosition += len;
////				if(curPosition > endPosition){
////					downLoadSize += len - (curPosition - endPosition) + 1;
////					Log.v("=downLoadSize=", "="+downLoadSize);
////				}else{
//					downLoadSize += len;
////				}
//					Message message = new Message();
//					message.what = 10;
//					message.obj = downLoadSize;
//					handler.sendMessage(message);
//			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			try {
				if(inputStream != null || raf != null || bis != null){
					bis.close();
					raf.close();
					inputStream.close();
				}
			} catch (Exception e2) {
			}
		}
	}
}

 

  • 大小: 43 KB
分享到:
评论
2 楼 cskymq 2012-07-24  
不要下载!  我靠,下载下来全是乱码! 看锤子
1 楼 daishengpu 2012-04-28  
怎么下载出来的是乱码  是否加密了呢

相关推荐

Global site tag (gtag.js) - Google Analytics