您的位置:首页 > 理论基础 > 计算机网络

网络多线线程下载并合并文件示例

2017-11-08 11:23 225 查看
  本示例的采用IO流与多线程下载同一张图片,下载完后进行合并;使用方法内创建线程方式,控制主线程的执行时机,即主线程调用方法,方法内创建线程,再返回调用方法的对象,随即往下执行其他程序,可有效防止主线程的其他方法在下载线程(即其他线程)未完成时执行,而出现数据错位缺失。

1 import java.io.*;
2 import java.net.URL;
3 import java.net.URLConnection;
4
5 /**
6  * Created by gdkong on 07/11/2017.
7  */
8
9 public class Test {
10
11     public static void main(String[] args) throws IOException, InterruptedException {
12         //主线程采用调用方法模式创建其他线程,可让其他线程执行完后才继续执行主线中的其他方法,此方式可控制主线的执行时机
13       multithreadedDownload ("http://localhost:8080/image/a.jpg","/Users/Shared/abc",3);
14     }
15
16     /**
17      * 多线程下载并合并文件,仅适用于Http协议,未尝试其他网络协议
18      * @param srcPath  下载源文件路径名
19      * @param destPath 保存文件夹路径名
20      * @param count    指定线程个数
21      */
22     public static void multithreadedDownload(String srcPath, String destPath, int count) throws IOException, InterruptedException {
23
24         //定义一个文件下载的文件夹路径
25         File dir = new File (destPath);
26         if (!dir.exists ()) {
27             dir.mkdirs ();
28         }
29         long total = getFileLength (srcPath);
30         //开启下载线程
31         OpenMultithreadedDownload (srcPath, dir, total, count);
32
33         //获取文件的后缀名
34         String suffix = srcPath.substring (srcPath.lastIndexOf ("."));
35         //合并文件
36         FileUtils.merge (dir, suffix);
37
38         System.out.println ("文件下载完成");
39     }
40
41     /**
42      * 多线程下载块
43      * @param path 下载源文件路径名
44      * @param dir 目标文件存储目录
45      * @param total 下载源文件大小
46      * @param count 指定线程个数
47      */
48     private static void OpenMultithreadedDownload(String path, File dir, long total, int count) throws InterruptedException {
49
50         //计算出每个线程平均现在的字节个数
51         long size = total / count;
52         //使用循环,计算每个线程下载开始和结束位置
53         for (int i = 1; i <= count; i++) {
54             //开始位置
55             long starIndex = (i - 1) * size;
56             //结束位置
57             long endIndex = i * size - 1;
58             //最后一个线程
59             if (i == 3) {
60                 endIndex = total - 1;
61             }
62             DownloadThread dt = new DownloadThread (path, dir, starIndex, endIndex, i);
63             dt.start ();
64         }
65     }
66
67     /**
68      * 获取下载源文件大小
69      * @param path 下载源文件路径名
70      * */
71     public static long getFileLength(String path) throws IOException {
72
73         URL url = new URL (path);
74         //获得连接对象
75         URLConnection con = url.openConnection ();
76         long total = con.getContentLengthLong ();
77         return total;
78     }
79     /**
80      * 合并文件功能
81      * @param dir 源文件存储的父目录
82      * @param suffix 文件的后缀名,用于过滤文件
83      */
84     public static void merge(File dir,String suffix) throws IOException {
85
86         File[] files = dir.listFiles (FileUtils.getFileFilter (suffix,false));
87         FileOutputStream fos = getFileOutputStream (dir, files[0]);
88
89         for(File file : files){
90             FileInputStream fis = new FileInputStream (file);
91             int len;
92             byte[] buf = new byte[8192];
93             while ((len=fis.read (buf)) != -1){
94                 fos.write (buf,0,len);
95             }
96             fis.close ();
97             //把已经合并过的文件删除
98             file.delete ();
99         }
100         fos.close ();
101     }
102     //获取合并文件输出流
103     private static FileOutputStream getFileOutputStream(File dir, File file) throws FileNotFoundException {
104         File file1 = file;
105         String name = file1.getName ();
106         name = name.substring (1);
107         File destFile = new File (dir,name);
108         return new FileOutputStream (destFile);
109     }
110     /**
111      * 文件过滤器
112      * @param suffix 文件后缀名
113      * @param containDirectory 是否显示子文件夹文件,true为显示,false不显示
114      */
115     public static FileFilter getFileFilter(String suffix,boolean containDirectory) {
116         return new FileFilter () {
117             @Override
118             public boolean accept(File file) {
119                 String name = file.getName ();
120                 boolean destFormat = file.isFile()&& name.endsWith(suffix);
121                 boolean b;
122
123                 b = containDirectory && file.isDirectory ();
124
125                 if (destFormat || b) return true;
126                 else return false;
127             }
128         };
129     }
130 }
131
132 //下载线程代码
133 class DownloadThread extends Thread {
134
135     private final String path;
136     private final File dir;
137     private final long startIndex;
138     private final long endIndex;
139     private final int threadID;
140   //使用构造方法传入参数
141     public DownloadThread(String path, File dir, long startIndex,
142                           long endIndex, int threadID) {
143         this.path = path;
144         this.dir = dir;
145         this.startIndex = startIndex;
146         this.endIndex = endIndex;
147         this.threadID = threadID;
148     }
149     @Override
150     public void run() {
151         try {
152             InputStream in = getInputStream ();
153             FileOutputStream fos = getFileOutputStream ();
154             int len ;
155             byte[] arr = new byte[8192];
156             while ((len = in.read (arr)) != -1){
157                 fos.write (arr,0,len);
158             }
159             in.close ();
160             fos.close ();
161         } catch (Exception e) {
162             e.printStackTrace ();
163         }
164
165     }
166     //获取下载输出流
167     private FileOutputStream getFileOutputStream() throws FileNotFoundException {
168         //获取到文件的名字
169         int index = path.lastIndexOf ("/")+1;
170         String name = path.substring (index);
171         File file = new File (dir,threadID+name);//创建目标文件键,防止文件覆盖
172         //创建一个输出流
173         return new FileOutputStream (file);
174     }
175     //获取下载的输入流
176     private InputStream getInputStream() throws IOException {
177         //创建一个URL对象
178         URL url= new URL (path);
179         //获取到连接对象
180         URLConnection con = url.openConnection ();
181         con.setRequestProperty ("Range","bytes="+startIndex+"-"+endIndex);
182         //获取到输入流
183         return con.getInputStream ();
184     }
185 }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: