• 《安卓网络编程》之第四篇 处理URL地址


      在Android手机系统中,可以通过URL地址获取网络资源。在URL类的众多方法中,可以使用openStream()方法来读取该URL资源的输入流InputStream。在此方法的基础上可以引申出很多重要的应用。在URL中,可以使用方法openConnection()返回一个URLConnection对象,该对象表示应用程序和URL之间的通信连接。程序可以通过URLConnection实例向该URL发送请求、读取URL引用的资源。

    下面的例子是在JAVA环境下使用URL实现多线程下载:

    多线程类DownTHhread

     1 import java.io.*;
     2 
     3 //定义下载从start到end的内容的线程
     4 class DownThread extends Thread {
     5     // 定义字节数组(取水的竹筒)的长度
     6     private final int BUFF_LEN = 32;
     7     // 定义下载的起始点
     8     private long start;
     9     // 定义下载的结束点
    10     private long end;
    11     // 下载资源对应的输入流
    12     private InputStream is;
    13     // 将下载到的字节输出到raf中
    14     private RandomAccessFile raf;
    15     
    16     // 构造器,传入输入流,输出流和下载起始点、结束点
    17     public DownThread(long start, long end, InputStream is, RandomAccessFile raf) {
    18         // 输出该线程负责下载的字节位置
    19         System.out.println(start + "---->" + end);
    20         this.start = start;
    21         this.end = end;
    22         this.is = is;
    23         this.raf = raf;    
    24     }
    25 
    26     public void run() {
    27         try {
    28             is.skip(start);
    29             raf.seek(start);
    30             // 定义读取输入流内容的缓存数组(竹筒)
    31             byte[] buff = new byte[BUFF_LEN];
    32             // 本线程负责下载资源的大小
    33             long contentLen = end - start;
    34             // 定义最多需要读取几次就可以完成本线程的下载
    35             long times = contentLen / BUFF_LEN + 4;
    36             // 实际读取的字节数
    37             int hasRead = 0;
    38             for (int i = 0; i < times; i++) {
    39                 hasRead = is.read(buff);
    40                 // 如果读取的字节数小于0,则退出循环!
    41                 if (hasRead < 0) {
    42                     break;
    43                 }
    44                 raf.write(buff, 0, hasRead);
    45             }
    46         } catch (Exception ex) {
    47             ex.printStackTrace();
    48         }
    49         // 使用finally块来关闭当前线程的输入流、输出流
    50         finally {
    51             try {
    52                 if (is != null) {
    53                     is.close();
    54                 }
    55                 if (raf != null) {
    56                     raf.close();
    57                 }
    58             } catch (Exception ex) {
    59                 ex.printStackTrace();
    60             }
    61         }
    62     }
    63 }

    类MutilDown:

     1 import java.io.*;
     2 import java.net.*;
     3 
     4 public class MutilDown {
     5     public static void main(String[] args) {
     6         final int DOWN_THREAD_NUM = 4;
     7         final String OUT_FILE_NAME = "down.jpg";
     8         InputStream[] isArr = new InputStream[DOWN_THREAD_NUM];
     9         RandomAccessFile[] outArr = new RandomAccessFile[DOWN_THREAD_NUM];
    10         try {
    11             // 创建一个URL对象
    12             URL url = new URL("http://images.china-pub.com/"
    13                     + "ebook35001-40000/35850/shupi.jpg");
    14             // 以此URL对象打开第一个输入流
    15             isArr[0] = url.openStream();
    16             long fileLen = getFileLength(url);
    17             System.out.println("网络资源的大小" + fileLen);
    18             // 以输出文件名创建第一个RandomAccessFile输出流
    19             outArr[0] = new RandomAccessFile(OUT_FILE_NAME, "rw");
    20             // 创建一个与下载资源相同大小的空文件
    21             for (int i = 0; i < fileLen; i++) {
    22                 outArr[0].write(0);
    23             }
    24             // 每线程应该下载的字节数
    25             long numPerThred = fileLen / DOWN_THREAD_NUM;
    26             // 整个下载资源整除后剩下的余数
    27             long left = fileLen % DOWN_THREAD_NUM;
    28             for (int i = 0; i < DOWN_THREAD_NUM; i++) {
    29                 // 为每个线程打开一个输入流、一个RandomAccessFile对象,
    30                 // 让每个线程分别负责下载资源的不同部分。
    31                 if (i != 0) {
    32                     // 以URL打开多个输入流
    33                     isArr[i] = url.openStream();
    34                     // 以指定输出文件创建多个RandomAccessFile对象
    35                     outArr[i] = new RandomAccessFile(OUT_FILE_NAME, "rw");
    36                 }
    37                 // 分别启动多个线程来下载网络资源
    38                 if (i == DOWN_THREAD_NUM - 1) {
    39                     // 最后一个线程下载指定numPerThred+left个字节
    40                     new DownThread(i * numPerThred, (i + 1) * numPerThred
    41                             + left, isArr[i], outArr[i]).start();
    42                 } else {
    43                     // 每个线程负责下载一定的numPerThred个字节
    44                     new DownThread(i * numPerThred, (i + 1) * numPerThred,
    45                             isArr[i], outArr[i]).start();
    46                 }
    47             }
    48         } catch (Exception ex) {
    49             ex.printStackTrace();
    50         }
    51     }
    52 
    53     // 定义获取指定网络资源的长度的方法
    54     // 定义获取指定网络资源的长度的方法
    55     public static long getFileLength(URL url) throws Exception {
    56         long length = 0;
    57         // 打开该URL对应的URLConnection。
    58         URLConnection con = url.openConnection();
    59         // 获取连接URL资源的长度
    60         long size = con.getContentLength();
    61         length = size;
    62         return length;
    63     }
    64 }

    上面的代码中类MutilDown按如下步骤实现多线程下载:

    1. 创建URL对象。
    2. 获取指定URL对象所指向资源的大小(由getFileLength方法实现),此处用到了URLConnection类,该类代表Java应用程序和URL之间的通信链接。
    3. 在本地磁盘上创建一个与网络资源相同大小的空文件。
    4. 计算每条线程应该下载网络资源的哪个部分(从哪个字节开始,到哪个字节结束)。
    5. 依次创建、启动多条线程来下载网络资源的指定部分。

    程序运行结果:

    网络资源的大小69281
    0---->17320
    17320---->34640
    34640---->51960
    51960---->69281

    工程对应目录会出现down.jpg

  • 相关阅读:
    volley框架使用
    Insert Interval
    candy(贪心)
    Best Time to Buy and Sell Stock
    Best Time to Buy and Sell Stock III
    distinct subsequences
    edit distance(编辑距离,两个字符串之间相似性的问题)
    trapping rain water
    word break II(单词切分)
    sudoku solver(数独)
  • 原文地址:https://www.cnblogs.com/hixin/p/4365705.html
Copyright © 2020-2023  润新知