Main.java
import java.net.HttpURLConnection; import java.net.URL; public class Main { private static Messages messages = new Messages(); private static CallBack callback = new CallBack() { @Override public void schedule(Messages messages) { long totalDownloadSize = messages.getTotalDownloadSize(); int currentDownloadSize = messages.getCurrentDownloadSize(); System.out.println((float)currentDownloadSize * 100.0f / (float)totalDownloadSize + "%"); } @Override public void handlerMessages(Messages messages) { } @Override public void fail(Messages messages) { System.out.println(messages.getMsg()); } }; public static void main(String[] args) throws Exception { long startTime = System.currentTimeMillis(); String downloadUrl = "http://www.xiazaiba.com/route.php?ct=stat&ac=stat_ads&id=CG8BOVNg&g=aHR0cDovL3d3dy51aWJpYS5jb20vamttc2V0dXAuZXhl"; URL url = new URL(downloadUrl); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setReadTimeout(1000 * 5); conn.setRequestProperty("Accept", "image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*"); conn.setRequestProperty("Accept-Language", "zh-CN"); conn.setRequestProperty("Referer", downloadUrl); conn.setRequestProperty("Charset", "UTF-8"); conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)"); conn.setRequestProperty("Connection", "Keep-Alive"); conn.connect(); if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { FileDownloader loader = new FileDownloader(callback, 4, messages); int size = conn.getContentLength();//根据响应获取文件大小 loader.setSavePath("E:\haoya.exe"); loader.setConfigPath("E:\haoya.properties"); loader.download(downloadUrl, size); }else{ System.out.println(conn.getResponseCode()); } conn.disconnect(); long endTime = System.currentTimeMillis(); System.out.println("Time" + (endTime - startTime)); } }
FileDownloader.java
import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.net.URL; import java.util.Map; public class FileDownloader implements DownLoadCallBack { //单个线程已经下载的长度 private int downloadSize; //线程数 private DownloadThread[] threads; // 每条线程下载的长度 private int block; //文件保存路径 private String savePath; //配置文件路径 private String configPath; private File saveFile; private boolean isNext; private int call_curr; private int call_total; private PropertiesHelper propertiesHelper; private Map<String, String> datas; private Messages messages; private CallBack callback; //总的下载长度 private int downloadLength; //是否退出下载 private boolean exit; public FileDownloader(CallBack callback, int threadNum, Messages messages) { this.callback = callback; this.threads = new DownloadThread[threadNum]; this.isNext = false; this.call_total = threadNum; this.downloadSize = 0; this.downloadLength = 0; this.messages = messages; this.exit = false; } /** * 开始下载文件 */ public void download(String downloadUrl, long size){ try { messages.setTotalDownloadSize(size); saveFile = new File(savePath); RandomAccessFile accessFile = new RandomAccessFile(saveFile, "rw"); accessFile.setLength(size); accessFile.close(); block = (int) ((size % this.threads.length) == 0 ? size / this.threads.length : size / this.threads.length + 1); URL url = new URL(downloadUrl); propertiesHelper = new PropertiesHelper(configPath); //如果配置文件不存在,则创建 if(!FileOperate.isFileExist(configPath)){ FileOperate.createFile(configPath, false); initProperties(); }else{ datas = propertiesHelper.getAllProperties(); if(datas.size() == 0) initProperties(); } for(int i = 0; i < threads.length; i++){ String value = datas.get(Constant.THREADID + (i + 1)); if(value == null) value = "0"; downloadSize = Integer.parseInt(value); downloadLength += downloadSize; } for (int i = 0; i < threads.length; i++) {// 开启线程进行下载 String value = datas.get(String.valueOf(Constant.THREADID + (i + 1))); if(value == null) value = "0"; downloadSize = Integer.parseInt(value); if(downloadSize == block){ call_curr++; if(call_curr == call_total){ isNext = true; break; } continue; } threads[i] = new DownloadThread(url, saveFile, block, downloadSize, i + 1, messages, callback, this); threads[i].setPriority(7); threads[i].start(); } while(!isNext()); } catch (IOException e) { messages.setMsg("FileDownloader:download:" + e.getMessage()); callback.fail(messages); } } private synchronized boolean isNext() { return isNext; } private void initProperties() { for(int i = 0; i < threads.length; i++){ propertiesHelper.setProperties(Constant.THREADID + (i + 1), "0"); } datas = propertiesHelper.getAllProperties(); } @Override public synchronized void isFinished() { call_curr++; if (call_curr == call_total){ isNext = true; } } public synchronized void update(String key, String value){ propertiesHelper.setProperties(key, value); } @Override public synchronized int getDownloadLength() { return downloadLength; } @Override public synchronized void append(int size) { downloadLength += size; } public String getSavePath() { return savePath; } public void setSavePath(String savePath) { this.savePath = savePath; } public String getConfigPath() { return configPath; } public void setConfigPath(String configPath) { this.configPath = configPath; } @Override public boolean getExit() { return exit; } @Override public void setExit(boolean isExit) { exit = isExit; } }
DownloadThread.java
import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.URL; public class DownloadThread extends Thread { private File saveFile; private URL downUrl; private int block; private int threadId = -1; private CallBack callback; private DownLoadCallBack downLoadCallBack; private int downloadSize; private Messages messages; public DownloadThread(URL downUrl, File saveFile, int block, int downloadSize, int threadId, Messages messages, CallBack callback, DownLoadCallBack downLoadCallBack) { this.downLoadCallBack = downLoadCallBack; this.downUrl = downUrl; this.saveFile = saveFile; this.block = block; this.threadId = threadId; this.callback = callback; this.downloadSize = downloadSize; this.messages = messages; } @Override public void run() { HttpURLConnection conn = null; InputStream inStream = null; RandomAccessFile threadfile = null; try { conn = (HttpURLConnection) downUrl.openConnection(); conn.setRequestMethod(Constant.GET); conn.setReadTimeout(1000 * 8); int startPos = block * (threadId - 1) + downloadSize;//开始位置 int endPos = block * threadId -1;//结束位置 conn.setRequestProperty("Range", "bytes=" + startPos + "-"+ endPos);//设置获取实体数据的范围 if(conn.getResponseCode() == HttpURLConnection.HTTP_PARTIAL){ inStream = conn.getInputStream(); byte[] buffer = new byte[Constant.BUFFER * 10]; int offset = 0; threadfile = new RandomAccessFile(saveFile, "rwd"); threadfile.seek(startPos); String key = Constant.THREADID + String.valueOf(threadId); //messages,文件总大小,下载的当前大小 while (!downLoadCallBack.getExit() && (offset = inStream.read(buffer)) != -1) { threadfile.write(buffer, 0, offset); downLoadCallBack.append(offset); downloadSize += offset; downLoadCallBack.update(key, String.valueOf(downloadSize)); int size = downLoadCallBack.getDownloadLength(); messages.setCurrentDownloadSize(size); callback.schedule(messages); } } } catch (IOException e) { downLoadCallBack.setExit(true); messages.setMsg("第" + threadId + "条线程下载失败"); callback.fail(messages); }finally{ try { if(threadfile != null){ threadfile.close(); } if(inStream != null){ inStream.close(); } if(conn != null){ conn.disconnect(); } } catch (IOException e) { e.printStackTrace(); } downLoadCallBack.isFinished(); } } }
DownLoadCallBack.java
public interface DownLoadCallBack { public void isFinished(); public void update(String key, String value); public void append(int size); public int getDownloadLength(); public boolean getExit(); public void setExit(boolean isExit); }
CallBack.java
public interface CallBack { public void handlerMessages(Messages messages); public void schedule(Messages messages); public void fail(Messages messages); }
FileOperate.java
import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; public class FileOperate { /** * 在指定路径下创建新文件 * @param filePath 文件路径 * @return * @throws IOException */ public static File createFile(String filePath, boolean isDeleteAllFiles) { String parentPath = filePath.substring(0, filePath.lastIndexOf(File.separator)); createFolders(parentPath, isDeleteAllFiles); File file = new File(filePath); try { if(!file.createNewFile()){ file.delete(); file.createNewFile(); } } catch (IOException e) { e.printStackTrace(); } return file; } /** * 判断配置文件是否存在 * @param filePath 文件路径 * @return */ public static boolean isFileExist(String filePath){ File file = new File(filePath); return file.exists(); } /** * 取得指定目录下的所有文件夹名 * @return */ public static List<String> getFilesName(String filePath){ List<String> files_name = null; File file = new File(filePath); if(file.exists()){ files_name = new ArrayList<String>(); File[] files = file.listFiles(); for (File file2 : files) { if(file2.isDirectory()){ files_name.add(file2.getName()); } } } return files_name; } public static void deleteFiles(File file){ if(file.exists()){ File[] files = file.listFiles(); for(File f : files){ if(f.isFile()) f.delete(); } } } public static File createFolders(String path, boolean isDeleteAllFiles){ File file = new File(path); if(file.exists() && file.isDirectory()){ if(isDeleteAllFiles) deleteFiles(file); }else{ file.mkdirs(); } return file; } public static boolean deleteFile(String filePath){ boolean isDeleted = false; File file = new File(filePath); if(file.exists()){ if(file.isFile()) { file.delete(); isDeleted = true; } } return isDeleted; } public static void deleteMkdir(String filePath){ File file = new File(filePath); if(file.exists() && file.isDirectory()){ file.delete(); } } /*********删除文件夹******/ public static boolean deleteFolders(String filePath){ boolean isDeleteSuccess = false; LinkedList<String> folderList = new LinkedList<String>(); folderList.add(filePath); while(folderList.size() > 0){ File file1 = new File(folderList.poll()); File[] files1 = file1.listFiles(); ArrayList<File> fileList = new ArrayList<File>(); for(int i = 0; i < fileList.size(); i++){ if(files1[i].isDirectory()){ folderList.add(files1[i].getPath()); }else{ fileList.add(files1[i]); } } //删除文件 for(File file : fileList){ file.delete(); } } //删除文件夹 folderList = new LinkedList<String>(); folderList.add(filePath); while(folderList.size() > 0){ File file2 = new File(folderList.getLast()); if(file2.delete()){ folderList.removeLast(); }else{ File[] files2 = file2.listFiles(); for(int i = 0; i < files2.length; i++){ folderList.add(files2[i].getPath()); } } } if(folderList.size() == 0) isDeleteSuccess = true; return isDeleteSuccess; } public static boolean moveFile(String srcFilePath, String dstFilePath){ boolean isMoveFileSuccess = false; BufferedInputStream bis = null; BufferedOutputStream bos = null; FileInputStream fis = null; FileOutputStream fos = null; try { if(isFileExist(dstFilePath)) deleteFile(dstFilePath); File dstFile = createFile(dstFilePath, false); fis = new FileInputStream(new File(srcFilePath)); fos = new FileOutputStream(dstFile); bis = new BufferedInputStream(fis); bos = new BufferedOutputStream(fos, Constant.BUFFER * 10); int count = -1; byte[] buffer = new byte[Constant.BUFFER * 10]; while((count = bis.read(buffer, 0, Constant.BUFFER * 10)) != -1){ bos.write(buffer, 0, count); bos.flush(); } isMoveFileSuccess = true; } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally{ try { if(bos != null){ bos.close(); } if(fos != null){ fos.close(); } if(bis != null){ bis.close(); } if(fis != null){ fis.close(); } } catch (IOException e) { e.printStackTrace(); } } return isMoveFileSuccess; } }
Constant.java
public class Constant { public static final int BUFFER = 1024; public static final String UTF = "utf-8"; public static final String THREADID = "threadId"; public static final String OGG = ".ogg"; public static final String PACK = ".pack"; public static final String PNG = ".png"; public static final String MP3 = ".mp3"; public static final String PROPERTIES = ".properties"; public static final String TMX = ".tmx"; public static final String GET = "GET"; }
Messages.java
public class Messages { private String msg; private long totalDownloadSize; private int currentDownloadSize; public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public long getTotalDownloadSize() { return totalDownloadSize; } public void setTotalDownloadSize(long totalDownloadSize) { this.totalDownloadSize = totalDownloadSize; } public int getCurrentDownloadSize() { return currentDownloadSize; } public void setCurrentDownloadSize(int currentDownloadSize) { this.currentDownloadSize = currentDownloadSize; } }
PropertiesHelper.java
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import java.util.Properties; public class PropertiesHelper { private String project_root = ""; public PropertiesHelper(String filePath) { if (filePath != null && filePath.length() > 0) { project_root = project_root + filePath; } } public String getProperties(String key) { InputStream fis = null; try { Properties prop = new Properties(); fis = new FileInputStream(project_root); prop.load(fis); return prop.getProperty(key); } catch (Exception e) { e.printStackTrace(); } finally { try { if (fis != null) fis.close(); } catch (Exception e) { e.printStackTrace(); } } return null; } public Map<String, String> getAllProperties() { InputStream fis = null; Map<String, String> params = new HashMap<String, String>(); try { Properties prop = new Properties(); fis = new FileInputStream(project_root); prop.load(fis); Enumeration en = prop.propertyNames(); while (en.hasMoreElements()) { String key = (String) en.nextElement(); String value = prop.getProperty(key); params.put(key, value); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (fis != null) fis.close(); } catch (Exception e) { e.printStackTrace(); } } return params; } public void setProperties(String key, String value) { Properties prop = new Properties(); FileOutputStream outputFile = null; InputStream fis = null; try { // 输入流和输出流要分开处理, 放一起会造成写入时覆盖以前的属性 fis = new FileInputStream(project_root); // 先载入已经有的属性文件 prop.load(fis); // 追加新的属性 prop.setProperty(key, value); // 写入属性 outputFile = new FileOutputStream(project_root); prop.store(outputFile, ""); outputFile.flush(); } catch (Exception e) { e.printStackTrace(); } finally { try { if (fis != null) fis.close(); if (outputFile != null) outputFile.close(); } catch (Exception e) { e.printStackTrace(); } } } }