views:

197

answers:

2

Hello friends, I was wanting to add multiple connections in the code below to be able to download files faster. Could someone help me? Thanks in advance.

public void run() {
    RandomAccessFile file = null;
    InputStream stream = null;

    try {
        // Open connection to URL.
        HttpURLConnection connection =
                (HttpURLConnection) url.openConnection();

        // Specify what portion of file to download.
        connection.setRequestProperty("Range",
                "bytes=" + downloaded + "-");

        // Connect to server.
        connection.connect();

        // Make sure response code is in the 200 range.
        if (connection.getResponseCode() / 100 != 2) {
            error();
        }

        // Check for valid content length.
        int contentLength = connection.getContentLength();
        if (contentLength < 1) {
            error();
        }

        /* Set the size for this download if it
        hasn't been already set. */
        if (size == -1) {
            size = contentLength;
            stateChanged();
        }

        // Open file and seek to the end of it.
        file = new RandomAccessFile("C:\\"+getFileName(url), "rw");
        file.seek(downloaded);

        stream = connection.getInputStream();
        while (status == DOWNLOADING) {
            /* Size buffer according to how much of the
            file is left to download. */
            byte buffer[];
            if (size - downloaded > MAX_BUFFER_SIZE) {
                buffer = new byte[MAX_BUFFER_SIZE];
            } else {
                buffer = new byte[size - downloaded];
            }

            // Read from server into buffer.
            int read = stream.read(buffer);
            if (read == -1) {
                break;
            }

            // Write buffer to file.
            file.write(buffer, 0, read);
            downloaded += read;
            stateChanged();
        }

        /* Change status to complete if this point was
        reached because downloading has finished. */
        if (status == DOWNLOADING) {
            status = COMPLETE;
            stateChanged();
        }
    } catch (Exception e) {
        error();
    } finally {
        // Close file.
        if (file != null) {
            try {
                file.close();
            } catch (Exception e) {
            }
        }

        // Close connection to server.
        if (stream != null) {
            try {
                stream.close();
            } catch (Exception e) {
            }
        }
    }
}
+1  A: 

You could use threads.

Put the code for downloading and updating the RandomAccessFile in a Thread/Runnable and start multiple instances of it.

Use a global counter (synchronized access) to keep track of how many threads finished downloading, and make the main thread wait until all threads have increased the counter before closing the file.

Make sure to synchronize all access to the RandomAccessFile, so that thread A can not call seek(somePosition) while thread B is writing to another part of the file.

Eric Eijkelenboom
Rather than synchronize on a single `RandomAccessFile`, give each thread its own file and let the OS manage synchronization at the disk buffer.
Anon
A: 

Make sure you profile what you come up with. It is possible that the overhead of multiple threads and the coordination between them could make you code slower. Do not do this unless you are certain this is a bottleneck, the code complexity will increase and debugging this is non-trivial.

Romain Hippeau