Android 多线程下载网络文件

Android 多线程下载网络文件

这里需要用到一个类RandomAccessFile,下面是JDK里面对此类的描述!

此类的实例支持对随机访问文件的读取和写入。随机访问文件的行为类似存储在文件系统中的一个大型 byte 数组。存在指向该隐含数组的光标或索引,称为文件指针;输入操作从文件指针开始读取字节,并随着对字节的读取而前移此文件指针。如果随机访问文件以读取/写入模式创建,则输出操作也可用;输出操作从文件指针开始写入字节,并随着对字节的写入而前移此文件指针。写入隐含数组的当前末尾之后的输出操作导致该数组扩展。该文件指针可以通过 getFilePointer 方法读取,并通过 seek 方法设置。

通常,如果此类中的所有读取例程在读取所需数量的字节之前已到达文件末尾,则抛出 EOFException(是一种 IOException)。如果由于某些原因无法读取任何字节,而不是在读取所需数量的字节之前已到达文件末尾,则抛出 IOException,而不是 EOFException。需要特别指出的是,如果流已被关闭,则可能抛出 IOException。 

该类有两个构造方法RandomAccessFile(File file/String name,String mode);

其中Mode如下表

r 以只读方式打开。调用结果对象的任何 write 方法都将导致抛出 IOException
rw 打开以便读取和写入。如果该文件尚不存在,则尝试创建该文件
rws 打开以便读取和写入,对于 "rw",还要求对文件的内容或元数据的每个更新都同步写入到底层存储设备
rwd 打开以便读取和写入,对于 "rw",还要求对文件内容的每个更新都同步写入到底层存储设备

 


 

下面是一个实例:

 

public class MulThreadDownLoad {
    public static void main(String[] args) {
        String path = "http://localhost:4484/WebSite1/21.bmp";// 一个本地web服务,指向一张图片
        try {
            new MulThreadDownLoad().download(path, 3);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void download(String path, int threadsize) throws Exception {
        URL url = new URL(path);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setConnectTimeout(5000);
        conn.setRequestMethod("GET");
        if (conn.getResponseCode() == 200) {
            int length = conn.getContentLength();
            File file = new File(getFilename(path));
            RandomAccessFile accessFile = new RandomAccessFile(file, "rwd");
            // 在本地生成一个长度为length的文件
            accessFile.setLength(length);
            accessFile.close();
            // 每条线程负责下载的数据量
            int block = length / threadsize == 0 ? length / threadsize : length / threadsize + 1;
            for (int threadid = 0; threadid < threadsize; threadid++) {
                new Thread(new Runa(threadid, block, url, file)).start();
            }
        } else
            System.out.println(conn.getResponseCode() + "");
    }

    private class Runa implements Runnable {
        private int threadid;
        private int block;
        private URL url;
        private File file;

        public Runa(int threadid, int block, URL url, File file) {
            this.threadid = threadid;
            this.block = block;
            this.url = url;
            this.file = file;
        }

        @Override
        public void run() {
            int start = threadid * block;// 计算该线程从网络文件的什么位置开始下载
            int end = (threadid + 1) * block - 1;// 计算该线程下载网络文件的结束位置
            try {
                RandomAccessFile accessFile = new RandomAccessFile(file, "rwd");// 创建从中读取和向其中写入(可选)的随机访问文件流
                accessFile.seek(start);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setConnectTimeout(5000);
                conn.setRequestMethod("GET");
                conn.setRequestProperty("Range", "bytes=" + start + "-" + end);// 设置从start开始下载,到end结束
                // if (conn.getResponseCode() == 200) {
    // 如果是分段下载,请求状态码不是200而是206!
                InputStream ins = conn.getInputStream();
                byte[] buffer = new byte[1024];
                int length = 0;
                while ((length = ins.read(buffer)) != -1) {
                    accessFile.write(buffer, 0, length);
                }
                accessFile.close();
                ins.close();
                // }

            } catch (Exception e) {

                e.printStackTrace();
            }
        }
    }
    private String getFilename(String path) {
        return path.substring(path.lastIndexOf("/") + 1);
    }
}

 下面是多线程下载原理图

Android 多线程下载网络文件

Android和JavaEE中,多线程下载原理相同。

转载于:https://www.cnblogs.com/a284628487/archive/2013/04/20/3033175.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/110156.html原文链接:https://javaforall.net

(0)
上一篇 2021年8月23日 下午2:00
下一篇 2021年8月23日 下午2:00


相关推荐

  • MySQL 字符集 注意事项

    MySQL 字符集 注意事项utf8 unicode ci 与 utf8 general ci 区别 utf8 unicode ci 和 utf8 general ci 对中英文来说没有实质的差别 utf8 general ci 校对速度快 但准确度稍差 utf8 unicode ci 准确度高 但校对速度稍慢 若数据库中有德语 法语或者俄语需求 需使用 utf8 unicode ci 其他情况用 utf8 general ci 即可 如果你想使用 gb2312 编码 那么建议你使用 latin1 作为数据表的默认字符集 这样就能直

    2025年12月12日
    6
  • java drawstring字体大小,JAVA中,drawstring 方法的用法,格式是什么啊

    java drawstring字体大小,JAVA中,drawstring 方法的用法,格式是什么啊啦啦啦额 68 的回答 Java 中 Graphics 类的 drawString 方法 i drawString Stringstr intx inty Stringstr 是可以在屏幕上显示的字符串 整数类型 x 和 y 是在图形窗口上保持 x 和 y 位置的变量 ii drawString AttributedCh 迭代器 intx inty 根据 TextAttribut 类的

    2026年3月18日
    1
  • 想养龙虾?OpenClaw硬件哪个最重要?

    想养龙虾?OpenClaw硬件哪个最重要?

    2026年3月13日
    5
  • git gui提交无法获知你的身份 20

    git gui提交无法获知你的身份 20

    2021年10月9日
    68
  • 互联网架构演变

    互联网架构演变互联网架构演变

    2022年4月22日
    41
  • 香农编码的gui编码_香农编码

    香农编码的gui编码_香农编码香农编码概念:香农编码是是采用信源符号的累计概率分布函数来分配字码的。香农编码是根据香农第一定理直接得出的,指出了平均码长与信息之间的关系,同时也指出了可以通过编码使平均码长达到极限值。香农第一定理是将原始信源符号转化为新的码符号,使码符号尽量服从等概分布,从而每个码符号所携带的信息量达到最大,进而可以用尽量少的码符号传输信源信息。香农编码属于不等长编码,通常将经常出现的消息变成短码,不经常出现的…

    2025年10月25日
    7

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号