繁体   English   中英

使用RandomAccessFile通过Java中的多线程下载不正确的文件

[英]Incorrect File download through Multithreading in Java using RandomAccessFile

你好,我尊敬的老年人:)

我的目标:通过使用Java中的多线程来下载给定URL的URL资源,即将单个文件下载为多个文件(类似于IDM的方式),并在下载结束时将所有文件合并为一个最终文件。 例如,如果一个映像为260KB,我想将其下载到2个线程中, 1st Thread应从0KB下载到130KB2nd Thread应从131KB to 260KB下载到131KB to 260KB

使用的技术: Java,RandomAccessFile,多线程,InputStreams

问题:此代码适用于1个线程,即,如果我运行一个从0到260KB开始的线程。 但是,当我尝试分批下载时,会发生以下错误:

  1. 它将下载额外的垃圾KB,即对于260KB文件,将下载300 + KB。

    要么

  2. 有时,确切的260KB已下载,但文件已损坏,我无法打开图像。

请帮我。 自整周以来,我已经尝试了很多次,但似乎无法理解问题所在。

初始代码

void InitiaeDownload
{


        HttpURLConnection uc = (HttpURLConnection) url.openConnection();
        uc.connect();
        long fileSize = uc.getContentLengthLong();
        System.out.println("File Size = "+ fileSize );
        uc.disconnect();

//------------------

        long chunkSize = (long) Math.ceil(fileSize/2);

        long startFrom = 0;
        long endRange = (startFrom + chunkSize) - 1;

        System.out.println("Chunk Size = " + chunkSize);
        System.out.println("Part 1 :: Start = " + startFrom + "\tEnd To = " + endRange);

        Thread t1 = new MyThread(url, file, startFrom, endRange);
        t1.start();

        startFrom += chunkSize;
        long temp = endRange + chunkSize;
        endRange = temp + (fileSize-temp);  //also add remaining bytes

        System.out.println("Part 2 :: Start = " + startFrom + "\tEnd To = " + endRange );

        Thread t2 = new MyThread(url, file, startFrom, endRange);
        t2.start();
}

现在

螺纹类

class MyThread extends Thread {

    private URL url;
    private long startFrom;
    private long range;
    private InputStream inStream;
    private RandomAccessFile file;


    public MyThread(URL url, RandomAccessFile file, long startFrom,  long range)    //parameterized constructor
    {

        this.url = url;
        this.file = file;
        this.startFrom = startFrom;
        this.range = range;

    }

    public void run() {

        System.out.println("Thread Running..");

        Thread.currentThread().setPriority(MAX_PRIORITY);

        System.setProperty("http.proxyHost", "192.168.10.50");
        System.setProperty("http.proxyPort", "8080");   

        HttpURLConnection uc = null;
        try  {

            uc = (HttpURLConnection) url.openConnection();

            uc.setRequestProperty("Range", "bytes="+startFrom+"-"+range);
            uc.connect();

            inStream = uc.getInputStream();
            System.out.println("Starting Download");

            int bytesRead = 0;
            byte[] buffer = new byte[ (int) (range-startFrom) ];


            file.seek(startFrom);   //adjusted start of file

            while( (bytesRead = inStream.read(buffer) ) != -1 ) {

                file.write(buffer, 0, bytesRead);
            }

            System.err.println("Download Completed!");
            uc.disconnect();
        }
        catch(IOException e) {
            System.err.println("Exception in " + Thread.currentThread().getName() + "\t Exception = " + e );
        }           
    }  ///END OF run()  
} ////END OF MyThread Class

您试图从多个线程写入同一file对象。 当您seek()或write()时,它只对执行位置有一个看法。

如果要一次在不同的位置写入相同的内容,则每个线程都必须具有其自己的RandomAccessFile对象,即使它们都指向同一个基础文件也是如此。

顺便说一句:更改IO绑定进程的线程优先级可能做的很少(除非您是管理员,否则什么也不会做)

首先:使用ExecutorService代替原始线程; 您将可以更轻松地管理工作。

第二:为什么每次文件大小为2? 更好的(恕我直言)将使用固定的块大小。

第三:使用FileChannel并成块地映射文件(使用FileChannel.open()获取通道)。

四:由于使用Java 7,因此请使用java.nio和try-with-resources;)

这是在文件中从偏移量1000(包括)写入偏移量2000(不包括)的方式。 请注意,文件大小会根据需要扩展!

// "channel" is your FileChannel.
// Argument to the worker: the channel, the offset, the size to write

final ByteBuffer buf = channel.map(FileChannel.MapMode.READ_WRITE, 1000L, 1000L);

try (
    final InputStream in = uc.getInputStream();    
    final ReadableByteChannel inChannel = Channels.newChannel(in);
) {
    inChannel.read(buf); // returns the number of bytes read
    channel.force(false);
}

这基本上就是您的一名工人的内容。

要隐藏文件,文件必须至少等于您说话的位置的长度。 因此,您必须首先创建具有结果大小的文件,然后根据您的搜索位置覆盖数据。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM