zoukankan      html  css  js  c++  java
  • 网络多线线程下载并合并文件示例

      本示例的采用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 }
  • 相关阅读:
    安装 windows 2008 解决 gpt 分区问题
    you have not created a boot efi partition
    echarts gauge 仪表盘去除外发光效果
    上国际网络——通过配置host
    juery 选择器 选择多个元素
    html5 <input> placeholder 属性
    PHP——字符串统一转码为GBK,自动判断是否UTF8并转码
    sublime text2 解决中文乱码
    PHP超级全局变量——Session 变量
    js为元素添加onclick事件
  • 原文地址:https://www.cnblogs.com/gdwkong/p/7803125.html
Copyright © 2011-2022 走看看