多线程java下载程序下载损坏的文件?

时间:2014-09-24 09:39:20

标签: java multithreading download-manager

我正在尝试在java中创建一个multiThread下载程序。它工作,但我下载的文件总是丢失一些字节。

我搜索并找到了许多多线程网页抓取工具的例子,但没有什么简单的,所以有人能告诉我我的方法是否可行吗?

我不知道问题是否是对字节进行排序。

我尝试过BlockingQueue但是没有用

URL url = new URL(mURL);
        final HttpURLConnection conn;
        conn = (HttpURLConnection) url.openConnection();
        conn.setConnectTimeout(10000);
        conn.connect();
        final BufferedInputStream in = new BufferedInputStream(conn.getInputStream());
        final File f = new File("tr.exe");
        if (f.exists()) {
            f.delete();
        }
        // open the output file and seek to the start location
        Thread t1 = new Thread() {
            public void run() {
                try {
                    RandomAccessFile raf = new RandomAccessFile(f, "rw");
                    raf.seek(0);
                    int numRead;
                    int mStartByte = 0;
                    byte data[] = new byte[conn.getContentLength() / 2];
                    while (((numRead = in.read(data, 0, 1024)) != -1) && (mStartByte < conn.getContentLength() / 2)) {
                        // write to buffer
                        raf.write(data, 0, numRead);
                        // increase the startByte for resume later
                        mStartByte += numRead;
                        // increase the downloaded size
                    }
                    raf.close();
                } catch (FileNotFoundException ex) {
                    Logger.getLogger(MyDownloader.class.getName()).log(Level.SEVERE, null, ex);
                } catch (IOException ex) {
                    Logger.getLogger(MyDownloader.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        };
        Thread t2 = new Thread() {
            public void run() {
                try {
                    RandomAccessFile raf = new RandomAccessFile(f, "rw");
                    raf.seek(conn.getContentLengthLong() / 2);
                    int numRead;
                    int mStartByte = conn.getContentLength() / 2;
                    byte data[] = new byte[conn.getContentLength() / 2];
                    while (((numRead = in.read(data, 0, 1024)) != -1) && (mStartByte < conn.getContentLength())) {
                        // write to buffer
                        raf.write(data, 0, numRead);
                        // increase the startByte for resume later
                        mStartByte += numRead;
                        // increase the downloaded size
                    }
                    raf.close();
                } catch (FileNotFoundException ex) {
                    Logger.getLogger(MyDownloader.class.getName()).log(Level.SEVERE, null, ex);
                } catch (IOException ex) {
                    Logger.getLogger(MyDownloader.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        };
        t1.start();
        t2.start();

2 个答案:

答案 0 :(得分:0)

发生了什么,正如我所说的那样,你是在同一时间写同一个文件,然后是订单改变,你甚至可能会丢失一些字节,现在应该做的是,写下一个文件的第一个线程的输出,例如'Thread1Output',第二个线程为'Thread2Output',并在最后将两个文件组合在一个文件中,希望它适用于你,祝你好运,对不起,我无法提供代码原因我从来没有创建过下载器= D

答案 1 :(得分:0)

这是我注意到的前几个问题......

  • 首先,我将您的下载/编写代码放在一个实现Runnable的单独类中,然后使用ExecutorService执行它。

  • byte[] data的大小应与您正在阅读的大块相同,并且您已将其硬编码为1024.

  • int mStartByte = conn.getContentLength() / 2如果长度是奇数,该怎么办?

  • 由于你有2个线程从同一个流读取,你不能保证例如。第一个线程读取上半部分,第二个线程读取下半部分。我怀疑它不适用于超过2048字节的文件。在每次阅读迭代中,您需要知道您在流中的位置,以便找到正确的位置。