本想直接在線學(xué)習(xí),不過網(wǎng)速實在不給力,寫了個多線程下載類,把官網(wǎng)下的實例全部下載下,包括圖片,java文件,xml文件。并按照相應(yīng)目錄進行存儲??傆嫊r間大概6分鐘左右下完。
先貼代碼:
再貼圖:
這是http://developer.android.com/resources/samples/ApiDemos/index.html頁面下的路徑格式
下面是保存下來的文件目錄格式:
代碼直接運行即可。
先貼代碼:
package com.multilThreadDownload;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/*
* 此類是用來獲取http://developer.android.com/resources
* 中的例子。
* */
public class GetFileFromWeb2 {
public static final int times = 4; //請求失敗繼續(xù)請求直到成功,最多請求4次
public static final String[] imageType={"png","gif","jpg"}; //聲明可讀取的圖片類型
public static final String fileName = "index.html"; //默認文件名
private static Map<String,String> map = new HashMap<String, String>(); //用來存儲下載失敗的文件及其地址信息
private static ArrayList<MultiThread> threadList = new ArrayList<MultiThread>();
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
String baseSavePath = "C:/Documents and Settings/Administrator/桌面/test/"; //寫到桌面
String basePath = "http://developer.android.com/resources/samples/ApiDemos/";
try {
oneKey2GetFile(basePath,baseSavePath);
} catch (Exception e) {
System.out.println("網(wǎng)絡(luò)斷開或不存在此頁面:"+basePath+fileName);
}
while (!threadList.isEmpty()) { //確保其他線程執(zhí)行完后計算時間
System.out.println("-------");
for(int i=0;i<threadList.size();i++){
MultiThread temp = threadList.get(i);
if(!temp.isAlive()){
threadList.remove(temp);
}
}
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("下載耗時:"+(System.currentTimeMillis()-startTime)+"ms");
System.out.println("===========保存出錯列表=============");
for(Map.Entry<String,String> entry:map.entrySet()){
String key = entry.getKey();
String value = entry.getValue();
System.out.println("文件名:"+key+"\t所在頁面:"+value);
}
}
/*
* 此方法用于遞歸調(diào)用
* 一鍵獲取此網(wǎng)頁文件下所有文件
* */
public static void oneKey2GetFile(String basePath,String baseSavePath)throws Exception{
String dirPath = createDir(basePath,baseSavePath); //獲取當前創(chuàng)建的目錄
String data = null;
try {
data = new String(getData(basePath,fileName)); //獲取上一層目錄數(shù)據(jù)
} catch (Exception e1) {
throw new Exception();
}
ArrayList<String> fileNames = dataFilter(data); //讀取上一層目錄數(shù)據(jù)獲取文件名
for(int i=0;i<fileNames.size();i++){ //遍歷依次讀取
String name = fileNames.get(i);
System.out.println(name);
if(name.endsWith("/")){ //表示是目錄
String newBasePath = basePath+name;
MultiThread multi = new MultiThread(newBasePath,dirPath);
threadList.add(multi);
multi.start();
}else{ //表示是文件或圖片
try {
byte[] files = getData(basePath,name);
filterSave(files,name,dirPath);
} catch (Exception e) {
System.out.println(fileNames.get(i)+"讀取出錯2");
}
}
}
}
/*
* 判斷獲取的文件名是否是圖片文件
* */
public static boolean containImage(String name){
for(int i=0;i<imageType.length;i++){
if(imageType[i].equals(name.substring(name.lastIndexOf('.')+1))){
return true;
}
}
return false;
}
/*
* 靜態(tài)方法獲取目錄名稱。并創(chuàng)建它。并返回目錄名稱
* */
public static String createDir(String path,String baseSavePath){
path = path.substring(0, path.length()-1);
String dir = path.substring(path.lastIndexOf('/')+1);
String dirPath = baseSavePath+dir;
System.out.println("保存路徑:"+dirPath);
File file = new File(dirPath);
if(!file.exists()){ //創(chuàng)建目錄
file.mkdirs();
}
return dirPath+"/";
}
/*
* 返回指定網(wǎng)頁路徑返回的數(shù)據(jù)字節(jié)流
* */
public static byte[] getData(String basePath,String fileName) throws Exception{
String fileName2 = fileName;
if(!containImage(fileName)){
fileName = fileName.replaceAll("\\.\\w+", "\\.html");
}
ByteArrayOutputStream byteArray =null;
for (int i = 0; i < times; i++) { // 指定請求次數(shù)
try {
URL url = new URL(basePath + fileName);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(10 * 1000);
conn.setRequestMethod("GET");
InputStream inStream = conn.getInputStream();
byte[] buff = new byte[1024];
byteArray = new ByteArrayOutputStream();
int len = 0;
while ((len = inStream.read(buff)) != -1) {
byteArray.write(buff, 0, len);
}
byteArray.flush();
byteArray.close();
inStream.close();
System.out.println(conn.getResponseCode());
if (conn.getResponseCode() == 200)
break; // 如果請求成功則終止循環(huán)
} catch (Exception e) {
if(i>=times-1){
map.put(fileName2, basePath+GetFileFromWeb2.fileName);
throw new Exception(); //請求大于指定次數(shù)后還不成功則拋出異常
}
}
}
return byteArray.toByteArray();
}
/*
* 讀取上一層目錄數(shù)據(jù)獲取文件名,
* 過濾文件,獲取指定的文件名數(shù)組
* */
public static ArrayList<String> dataFilter(String data){
Pattern p = Pattern.compile("<a href=\".*\">\\s*(.+/|.*\\.(xml|java|png|gif|jpg))\\s*</a>"); //匹配單個文件或目錄
Matcher matcher = p.matcher(data);
ArrayList<String> fileNames = new ArrayList<String>();
while(matcher.find()){
fileNames.add(matcher.group(1));
}
return fileNames;
}
/*
* 過濾獲取指定的xml或java文件。并保存文件
* */
public static void filterSave(byte[] fileBytes,String fileName,String dirPath) throws Exception{
String fileData = new String(fileBytes);
String name = dirPath + fileName;
if(containImage(fileName)){ //判斷是否是圖片
FileOutputStream outStream = new FileOutputStream(name);
outStream.write(fileBytes, 0, fileBytes.length); // 寫入圖片內(nèi)容
outStream.flush();
outStream.close();
}else{
fileData = fileData.replaceAll("<", "<");
fileData = fileData.replaceAll(">", ">");
/*由于存在大量的回車換行,
* 需先行替換,不然匹配不出內(nèi)容,
* 注意有些文件可能還含有/r,也要替換
* */
fileData = fileData.replaceAll("\n", "#@");
Pattern p = Pattern.compile("<pre>(.*)</pre>");
Matcher matcher = p.matcher(fileData);
while(matcher.find()){
String str = matcher.group(1).replaceAll("#@", "\n"); //匹配到后再替換回來
File file = new File(name);
FileWriter writer = new FileWriter(file);
writer.write(str, 0, str.length());
writer.flush();
writer.close();
}
}
System.out.println(name);
}
static class MultiThread extends Thread{
private String basePath;
private String baseSavePath;
public MultiThread(){
}
public MultiThread(String basePath,String baseSavePath){
this.basePath = basePath;
this.baseSavePath = baseSavePath;
}
@Override
public void run(){
try {
oneKey2GetFile(basePath,baseSavePath);
} catch (Exception e) {
System.out.println("讀取目錄:"+basePath+" 出錯");
}
}
}
}
再貼圖:
這是http://developer.android.com/resources/samples/ApiDemos/index.html頁面下的路徑格式
下面是保存下來的文件目錄格式:
代碼直接運行即可。
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

