Java 限制输入流

Java 限制输入流,java,rate-limiting,Java,Rate Limiting,我对Java很陌生。我编写了一个Swing应用程序,可以通过internet下载特定的文件 我想做的是将InputStream限制为每秒读取n(比如说10240字节,这可能会改变)字节 读取整个文件后,它应将文件保存到本地目录中,如C:\Downloads\ 我猜我应该创建一个扩展到InputStream并覆盖其方法的类,但我不确定如何以及哪些方法可以实现我的目标 我使用HTTP下载示例和FTP示例 HTTP示例 package net.codejava.networking; import

我对Java很陌生。我编写了一个Swing应用程序,可以通过internet下载特定的文件

我想做的是将
InputStream
限制为每秒读取
n
(比如说10240字节,这可能会改变)字节

读取整个文件后,它应将文件保存到本地目录中,如
C:\Downloads\

我猜我应该创建一个扩展到
InputStream
并覆盖其方法的类,但我不确定如何以及哪些方法可以实现我的目标

我使用HTTP下载示例和FTP示例

HTTP示例

package net.codejava.networking;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * A utility that downloads a file from a URL.
 * @author www.codejava.net
 *
 */
public class HttpDownloadUtility {
    private static final int BUFFER_SIZE = 4096;

    /**
     * Downloads a file from a URL
     * @param fileURL HTTP URL of the file to be downloaded
     * @param saveDir path of the directory to save the file
     * @throws IOException
     */
    public static void downloadFile(String fileURL, String saveDir)
            throws IOException {
        URL url = new URL(fileURL);
        HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
        int responseCode = httpConn.getResponseCode();

        // always check HTTP response code first
        if (responseCode == HttpURLConnection.HTTP_OK) {
            String fileName = "";
            String disposition = httpConn.getHeaderField("Content-Disposition");
            String contentType = httpConn.getContentType();
            int contentLength = httpConn.getContentLength();

            if (disposition != null) {
                // extracts file name from header field
                int index = disposition.indexOf("filename=");
                if (index > 0) {
                    fileName = disposition.substring(index + 10,
                            disposition.length() - 1);
                }
            } else {
                // extracts file name from URL
                fileName = fileURL.substring(fileURL.lastIndexOf("/") + 1,
                        fileURL.length());
            }

            System.out.println("Content-Type = " + contentType);
            System.out.println("Content-Disposition = " + disposition);
            System.out.println("Content-Length = " + contentLength);
            System.out.println("fileName = " + fileName);

            // opens input stream from the HTTP connection
            InputStream inputStream = httpConn.getInputStream();
            String saveFilePath = saveDir + File.separator + fileName;

            // opens an output stream to save into file
            FileOutputStream outputStream = new FileOutputStream(saveFilePath);

            int bytesRead = -1;
            byte[] buffer = new byte[BUFFER_SIZE];
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }

            outputStream.close();
            inputStream.close();

            System.out.println("File downloaded");
        } else {
            System.out.println("No file to download. Server replied HTTP code: " + responseCode);
        }
        httpConn.disconnect();
    }
}
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;

/**
 * A program demonstrates how to upload files from local computer to a remote
 * FTP server using Apache Commons Net API.
 * @author www.codejava.net
 */
public class FTPDownloadFileDemo {

    public static void main(String[] args) {
        String server = "www.myserver.com";
        int port = 21;
        String user = "user";
        String pass = "pass";

        FTPClient ftpClient = new FTPClient();
        try {

            ftpClient.connect(server, port);
            ftpClient.login(user, pass);
            ftpClient.enterLocalPassiveMode();
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);

            // APPROACH #1: using retrieveFile(String, OutputStream)
            String remoteFile1 = "/test/video.mp4";
            File downloadFile1 = new File("D:/Downloads/video.mp4");
            OutputStream outputStream1 = new BufferedOutputStream(new FileOutputStream(downloadFile1));
            boolean success = ftpClient.retrieveFile(remoteFile1, outputStream1);
            outputStream1.close();

            if (success) {
                System.out.println("File #1 has been downloaded successfully.");
            }

            // APPROACH #2: using InputStream retrieveFileStream(String)
            String remoteFile2 = "/test/song.mp3";
            File downloadFile2 = new File("D:/Downloads/song.mp3");
            OutputStream outputStream2 = new BufferedOutputStream(new FileOutputStream(downloadFile2));
            InputStream inputStream = ftpClient.retrieveFileStream(remoteFile2);
            byte[] bytesArray = new byte[4096];
            int bytesRead = -1;
            while ((bytesRead = inputStream.read(bytesArray)) != -1) {
                outputStream2.write(bytesArray, 0, bytesRead);
            }

            success = ftpClient.completePendingCommand();
            if (success) {
                System.out.println("File #2 has been downloaded successfully.");
            }
            outputStream2.close();
            inputStream.close();

        } catch (IOException ex) {
            System.out.println("Error: " + ex.getMessage());
            ex.printStackTrace();
        } finally {
            try {
                if (ftpClient.isConnected()) {
                    ftpClient.logout();
                    ftpClient.disconnect();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }
}
FTP示例

package net.codejava.networking;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * A utility that downloads a file from a URL.
 * @author www.codejava.net
 *
 */
public class HttpDownloadUtility {
    private static final int BUFFER_SIZE = 4096;

    /**
     * Downloads a file from a URL
     * @param fileURL HTTP URL of the file to be downloaded
     * @param saveDir path of the directory to save the file
     * @throws IOException
     */
    public static void downloadFile(String fileURL, String saveDir)
            throws IOException {
        URL url = new URL(fileURL);
        HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
        int responseCode = httpConn.getResponseCode();

        // always check HTTP response code first
        if (responseCode == HttpURLConnection.HTTP_OK) {
            String fileName = "";
            String disposition = httpConn.getHeaderField("Content-Disposition");
            String contentType = httpConn.getContentType();
            int contentLength = httpConn.getContentLength();

            if (disposition != null) {
                // extracts file name from header field
                int index = disposition.indexOf("filename=");
                if (index > 0) {
                    fileName = disposition.substring(index + 10,
                            disposition.length() - 1);
                }
            } else {
                // extracts file name from URL
                fileName = fileURL.substring(fileURL.lastIndexOf("/") + 1,
                        fileURL.length());
            }

            System.out.println("Content-Type = " + contentType);
            System.out.println("Content-Disposition = " + disposition);
            System.out.println("Content-Length = " + contentLength);
            System.out.println("fileName = " + fileName);

            // opens input stream from the HTTP connection
            InputStream inputStream = httpConn.getInputStream();
            String saveFilePath = saveDir + File.separator + fileName;

            // opens an output stream to save into file
            FileOutputStream outputStream = new FileOutputStream(saveFilePath);

            int bytesRead = -1;
            byte[] buffer = new byte[BUFFER_SIZE];
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }

            outputStream.close();
            inputStream.close();

            System.out.println("File downloaded");
        } else {
            System.out.println("No file to download. Server replied HTTP code: " + responseCode);
        }
        httpConn.disconnect();
    }
}
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;

/**
 * A program demonstrates how to upload files from local computer to a remote
 * FTP server using Apache Commons Net API.
 * @author www.codejava.net
 */
public class FTPDownloadFileDemo {

    public static void main(String[] args) {
        String server = "www.myserver.com";
        int port = 21;
        String user = "user";
        String pass = "pass";

        FTPClient ftpClient = new FTPClient();
        try {

            ftpClient.connect(server, port);
            ftpClient.login(user, pass);
            ftpClient.enterLocalPassiveMode();
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);

            // APPROACH #1: using retrieveFile(String, OutputStream)
            String remoteFile1 = "/test/video.mp4";
            File downloadFile1 = new File("D:/Downloads/video.mp4");
            OutputStream outputStream1 = new BufferedOutputStream(new FileOutputStream(downloadFile1));
            boolean success = ftpClient.retrieveFile(remoteFile1, outputStream1);
            outputStream1.close();

            if (success) {
                System.out.println("File #1 has been downloaded successfully.");
            }

            // APPROACH #2: using InputStream retrieveFileStream(String)
            String remoteFile2 = "/test/song.mp3";
            File downloadFile2 = new File("D:/Downloads/song.mp3");
            OutputStream outputStream2 = new BufferedOutputStream(new FileOutputStream(downloadFile2));
            InputStream inputStream = ftpClient.retrieveFileStream(remoteFile2);
            byte[] bytesArray = new byte[4096];
            int bytesRead = -1;
            while ((bytesRead = inputStream.read(bytesArray)) != -1) {
                outputStream2.write(bytesArray, 0, bytesRead);
            }

            success = ftpClient.completePendingCommand();
            if (success) {
                System.out.println("File #2 has been downloaded successfully.");
            }
            outputStream2.close();
            inputStream.close();

        } catch (IOException ex) {
            System.out.println("Error: " + ex.getMessage());
            ex.printStackTrace();
        } finally {
            try {
                if (ftpClient.isConnected()) {
                    ftpClient.logout();
                    ftpClient.disconnect();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }
}
我想限制这两个输入流的下载速率,这样当从远程位置获取这些文件时,下载速度会受到限制


如果你能给我一个简单的解释,我将不胜感激。

这有点原始,但它应该满足你的要求(虽然没有测试)

如果
BUFFER\u SIZE
不是
MAX\u BYTES\u PER\u SECOND
的一个系数,并且您对节流速率很挑剔,那么您可能需要使用
read()
重载,该重载接受偏移量并限制参数,以精确读取正确的量


要获得更清洁的解决方案,您可以使用番石榴的
RateLimitor

RateLimiter limiter = RateLimiter.create(MAX_BYTES_PER_SECOND);
while ((bytesRead = inputStream.read(buffer)) != -1) {
    outputStream.write(buffer, 0, bytesRead);
    limiter.acquire(bytesRead);
}

这有点原始,但它应该满足您的要求(但没有测试)

如果
BUFFER\u SIZE
不是
MAX\u BYTES\u PER\u SECOND
的一个系数,并且您对节流速率很挑剔,那么您可能需要使用
read()
重载,该重载接受偏移量并限制参数,以精确读取正确的量


要获得更清洁的解决方案,您可以使用番石榴的
RateLimitor

RateLimiter limiter = RateLimiter.create(MAX_BYTES_PER_SECOND);
while ((bytesRead = inputStream.read(buffer)) != -1) {
    outputStream.write(buffer, 0, bytesRead);
    limiter.acquire(bytesRead);
}

实际上,您可以扩展
java.util.TimerTask
,而不是扩展
InputStream
。然后使用
java.util.Timer
可以安排一个任务,该任务每秒执行一次,直到下载整个文件。因此,您只需定义一秒钟内要下载的字节数。有时下载可能低于您提供的限制(由于网络延迟或其他原因),但这不是冲突,因为在任何情况下,您的下载速率都会低于您提供的限制。此外,您可以随时更改下载速率,即使在下载过程中也是如此。HTTP/HTTPS实现的示例如下:

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.NumberFormat;
import java.util.Timer;
import java.util.TimerTask;

public class DownloaderWithLimit extends TimerTask
{
    private InputStream inputStream;
    private OutputStream outputStream;

    private int bytePerSecondLimit;
    private Timer timer;
    private float contentLength;
    private float downloadedLength;

    public DownloaderWithLimit (String urlToDownload, String destFileFullPath, int bytePerSecondLimit) throws IOException
    {
        this.bytePerSecondLimit = bytePerSecondLimit;
        //
        inputStream = createInputStreamFromUrl ( urlToDownload );
        outputStream = new FileOutputStream ( new File ( destFileFullPath ) );
    }

    public void start(){
        timer = new Timer();
        timer.scheduleAtFixedRate(this, 1000, 1000);
    }

    public void run () 
    {
        try
        {
            byte[] buffer = new byte[bytePerSecondLimit];
            int bytesRead = inputStream.read(buffer);
            if(bytesRead != -1){
                outputStream.write(buffer, 0, bytesRead);
            } else {
                outputStream.close();
                inputStream.close();
                timer.cancel();
            }
            downloadedLength += bytesRead;
            System.out.println (bytesRead + " bytes per second. "+ NumberFormat.getPercentInstance ().format ( downloadedLength/contentLength )+" completed...");
        }
        catch ( IOException e )
        {
            e.printStackTrace();
            throw new RuntimeException ( "Error During Download..." , e.getCause () );
        }
    }

    private InputStream createInputStreamFromUrl ( String fileUrl ) throws IOException
    {
        URL url = new URL ( fileUrl );
        HttpURLConnection httpConn = (HttpURLConnection) url.openConnection ();
        int responseCode = httpConn.getResponseCode ();

        // always check HTTP response code first
        if ( responseCode == HttpURLConnection.HTTP_OK )
        {
            String fileName = "";
            String disposition = httpConn
                    .getHeaderField ( "Content-Disposition" );
            String contentType = httpConn.getContentType ();
            contentLength = httpConn.getContentLength ();

            if ( disposition != null )
            {
                // extracts file name from header field
                int index = disposition.indexOf ( "filename=" );
                if ( index > 0 )
                {
                    fileName = disposition.substring ( index + 10 , disposition.length () - 1 );
                }
            }
            else
            {
                // extracts file name from URL
                fileName = fileUrl.substring ( fileUrl.lastIndexOf ( "/" ) + 1 , fileUrl.length () );
            }

            System.out.println ( "Content-Type = " + contentType );
            System.out.println ( "Content-Disposition = " + disposition );
            System.out.println ( "Content-Length = " + contentLength );
            System.out.println ( "fileName = " + fileName );

            // opens input stream from the HTTP connection
            InputStream inputStream = httpConn.getInputStream ();

            return inputStream;
        }

        return null;
    }

    /**
     * @return the bytePerSecondLimit
     */
    public int getBytePerSecondLimit ()
    {
        return bytePerSecondLimit;
    }

    /**
     * @param bytePerSecondLimit the bytePerSecondLimit to set
     */
    public void setBytePerSecondLimit ( int bytePerSecondLimit )
    {
        this.bytePerSecondLimit = bytePerSecondLimit;
    }

    public static void main ( String[] args ) throws IOException
    {
        DownloaderWithLimit d = new DownloaderWithLimit ( "https://download.mozilla.org/?product=firefox-46.0.1-SSL&os=win64&lang=en-US" , "c:/firefox-46.0.1_x64.exe" , 10240);//10Kb/s
        d.start ();
    }
}
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.NumberFormat;
import java.util.Timer;
import java.util.TimerTask;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;


public class FtpDownloaderWithLimit extends TimerTask
{
    private InputStream inputStream;
    private OutputStream outputStream;

    private int bytePerSecondLimit;
    private Timer timer;
    private float contentLength;
    private float downloadedLength;
    private FTPClient ftpClient;

    public FtpDownloaderWithLimit (String ftpServer, int port, String username, String password, String srcFileRelativePath, String destFileFullPath, int bytePerSecondLimit) throws IOException
    {
        this.bytePerSecondLimit = bytePerSecondLimit;
        //
        inputStream = createInputStreamFromUrl ( ftpServer, port, username, password, srcFileRelativePath );
        outputStream = new FileOutputStream ( new File ( destFileFullPath ) );
    }

    public void start(){
        timer = new Timer();
        timer.scheduleAtFixedRate(this, 1000, 1000);
    }

    public void run () 
    {
        try
        {
            byte[] buffer = new byte[bytePerSecondLimit];
            int bytesRead = inputStream.read(buffer);
            if(bytesRead != -1){
                outputStream.write(buffer, 0, bytesRead);
            } else {
                boolean success = ftpClient.completePendingCommand();
                if (success) {
                    System.out.println("File #2 has been downloaded successfully.");
                }
                outputStream.close();
                inputStream.close();
                timer.cancel();
            }
            downloadedLength += bytesRead;
            System.out.println (bytesRead + " bytes per second. "+ NumberFormat.getPercentInstance ().format ( downloadedLength/contentLength )+" completed...");
        }
        catch ( IOException e )
        {
            e.printStackTrace();
            throw new RuntimeException ( "Error During Download..." , e.getCause () );
        }
    }

    private InputStream createInputStreamFromUrl(String ftpServer, int port,
            String username, String password, String srcFileRelativePath) throws IOException{

        ftpClient = new FTPClient();
        ftpClient.connect(ftpServer, port);
        ftpClient.login(username, password);
        ftpClient.enterLocalPassiveMode();
        ftpClient.setFileType(FTP.BINARY_FILE_TYPE);

        InputStream inputStream = ftpClient.retrieveFileStream(srcFileRelativePath);

        return inputStream;
    }

    /**
     * @return the bytePerSecondLimit
     */
    public int getBytePerSecondLimit ()
    {
        return bytePerSecondLimit;
    }

    /**
     * @param bytePerSecondLimit the bytePerSecondLimit to set
     */
    public void setBytePerSecondLimit ( int bytePerSecondLimit )
    {
        this.bytePerSecondLimit = bytePerSecondLimit;
    }

    public static void main ( String[] args ) throws IOException
    {
        FtpDownloaderWithLimit d = new FtpDownloaderWithLimit ( "www.myserver.com" , 9111 /*sample port*/, "USERNAME", "PASSWORD", "/My/File/To/Downlaod.xxx", "c:/your-path-to-dest-file" , 10240);//10Kb/s
        d.start ();
    }

}
具有利率限制的FTP样本如下:

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.NumberFormat;
import java.util.Timer;
import java.util.TimerTask;

public class DownloaderWithLimit extends TimerTask
{
    private InputStream inputStream;
    private OutputStream outputStream;

    private int bytePerSecondLimit;
    private Timer timer;
    private float contentLength;
    private float downloadedLength;

    public DownloaderWithLimit (String urlToDownload, String destFileFullPath, int bytePerSecondLimit) throws IOException
    {
        this.bytePerSecondLimit = bytePerSecondLimit;
        //
        inputStream = createInputStreamFromUrl ( urlToDownload );
        outputStream = new FileOutputStream ( new File ( destFileFullPath ) );
    }

    public void start(){
        timer = new Timer();
        timer.scheduleAtFixedRate(this, 1000, 1000);
    }

    public void run () 
    {
        try
        {
            byte[] buffer = new byte[bytePerSecondLimit];
            int bytesRead = inputStream.read(buffer);
            if(bytesRead != -1){
                outputStream.write(buffer, 0, bytesRead);
            } else {
                outputStream.close();
                inputStream.close();
                timer.cancel();
            }
            downloadedLength += bytesRead;
            System.out.println (bytesRead + " bytes per second. "+ NumberFormat.getPercentInstance ().format ( downloadedLength/contentLength )+" completed...");
        }
        catch ( IOException e )
        {
            e.printStackTrace();
            throw new RuntimeException ( "Error During Download..." , e.getCause () );
        }
    }

    private InputStream createInputStreamFromUrl ( String fileUrl ) throws IOException
    {
        URL url = new URL ( fileUrl );
        HttpURLConnection httpConn = (HttpURLConnection) url.openConnection ();
        int responseCode = httpConn.getResponseCode ();

        // always check HTTP response code first
        if ( responseCode == HttpURLConnection.HTTP_OK )
        {
            String fileName = "";
            String disposition = httpConn
                    .getHeaderField ( "Content-Disposition" );
            String contentType = httpConn.getContentType ();
            contentLength = httpConn.getContentLength ();

            if ( disposition != null )
            {
                // extracts file name from header field
                int index = disposition.indexOf ( "filename=" );
                if ( index > 0 )
                {
                    fileName = disposition.substring ( index + 10 , disposition.length () - 1 );
                }
            }
            else
            {
                // extracts file name from URL
                fileName = fileUrl.substring ( fileUrl.lastIndexOf ( "/" ) + 1 , fileUrl.length () );
            }

            System.out.println ( "Content-Type = " + contentType );
            System.out.println ( "Content-Disposition = " + disposition );
            System.out.println ( "Content-Length = " + contentLength );
            System.out.println ( "fileName = " + fileName );

            // opens input stream from the HTTP connection
            InputStream inputStream = httpConn.getInputStream ();

            return inputStream;
        }

        return null;
    }

    /**
     * @return the bytePerSecondLimit
     */
    public int getBytePerSecondLimit ()
    {
        return bytePerSecondLimit;
    }

    /**
     * @param bytePerSecondLimit the bytePerSecondLimit to set
     */
    public void setBytePerSecondLimit ( int bytePerSecondLimit )
    {
        this.bytePerSecondLimit = bytePerSecondLimit;
    }

    public static void main ( String[] args ) throws IOException
    {
        DownloaderWithLimit d = new DownloaderWithLimit ( "https://download.mozilla.org/?product=firefox-46.0.1-SSL&os=win64&lang=en-US" , "c:/firefox-46.0.1_x64.exe" , 10240);//10Kb/s
        d.start ();
    }
}
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.NumberFormat;
import java.util.Timer;
import java.util.TimerTask;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;


public class FtpDownloaderWithLimit extends TimerTask
{
    private InputStream inputStream;
    private OutputStream outputStream;

    private int bytePerSecondLimit;
    private Timer timer;
    private float contentLength;
    private float downloadedLength;
    private FTPClient ftpClient;

    public FtpDownloaderWithLimit (String ftpServer, int port, String username, String password, String srcFileRelativePath, String destFileFullPath, int bytePerSecondLimit) throws IOException
    {
        this.bytePerSecondLimit = bytePerSecondLimit;
        //
        inputStream = createInputStreamFromUrl ( ftpServer, port, username, password, srcFileRelativePath );
        outputStream = new FileOutputStream ( new File ( destFileFullPath ) );
    }

    public void start(){
        timer = new Timer();
        timer.scheduleAtFixedRate(this, 1000, 1000);
    }

    public void run () 
    {
        try
        {
            byte[] buffer = new byte[bytePerSecondLimit];
            int bytesRead = inputStream.read(buffer);
            if(bytesRead != -1){
                outputStream.write(buffer, 0, bytesRead);
            } else {
                boolean success = ftpClient.completePendingCommand();
                if (success) {
                    System.out.println("File #2 has been downloaded successfully.");
                }
                outputStream.close();
                inputStream.close();
                timer.cancel();
            }
            downloadedLength += bytesRead;
            System.out.println (bytesRead + " bytes per second. "+ NumberFormat.getPercentInstance ().format ( downloadedLength/contentLength )+" completed...");
        }
        catch ( IOException e )
        {
            e.printStackTrace();
            throw new RuntimeException ( "Error During Download..." , e.getCause () );
        }
    }

    private InputStream createInputStreamFromUrl(String ftpServer, int port,
            String username, String password, String srcFileRelativePath) throws IOException{

        ftpClient = new FTPClient();
        ftpClient.connect(ftpServer, port);
        ftpClient.login(username, password);
        ftpClient.enterLocalPassiveMode();
        ftpClient.setFileType(FTP.BINARY_FILE_TYPE);

        InputStream inputStream = ftpClient.retrieveFileStream(srcFileRelativePath);

        return inputStream;
    }

    /**
     * @return the bytePerSecondLimit
     */
    public int getBytePerSecondLimit ()
    {
        return bytePerSecondLimit;
    }

    /**
     * @param bytePerSecondLimit the bytePerSecondLimit to set
     */
    public void setBytePerSecondLimit ( int bytePerSecondLimit )
    {
        this.bytePerSecondLimit = bytePerSecondLimit;
    }

    public static void main ( String[] args ) throws IOException
    {
        FtpDownloaderWithLimit d = new FtpDownloaderWithLimit ( "www.myserver.com" , 9111 /*sample port*/, "USERNAME", "PASSWORD", "/My/File/To/Downlaod.xxx", "c:/your-path-to-dest-file" , 10240);//10Kb/s
        d.start ();
    }

}

希望这会有帮助。

您实际上可以扩展
java.util.TimerTask
而不是扩展
InputStream
。然后使用
java.util.Timer
可以安排一个任务,该任务每秒执行一次,直到下载整个文件。因此,您只需定义一秒钟内要下载的字节数。有时下载可能低于您提供的限制(由于网络延迟或其他原因),但这不是冲突,因为在任何情况下,您的下载速率都会低于您提供的限制。此外,您可以随时更改下载速率,即使在下载过程中也是如此。HTTP/HTTPS实现的示例如下:

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.NumberFormat;
import java.util.Timer;
import java.util.TimerTask;

public class DownloaderWithLimit extends TimerTask
{
    private InputStream inputStream;
    private OutputStream outputStream;

    private int bytePerSecondLimit;
    private Timer timer;
    private float contentLength;
    private float downloadedLength;

    public DownloaderWithLimit (String urlToDownload, String destFileFullPath, int bytePerSecondLimit) throws IOException
    {
        this.bytePerSecondLimit = bytePerSecondLimit;
        //
        inputStream = createInputStreamFromUrl ( urlToDownload );
        outputStream = new FileOutputStream ( new File ( destFileFullPath ) );
    }

    public void start(){
        timer = new Timer();
        timer.scheduleAtFixedRate(this, 1000, 1000);
    }

    public void run () 
    {
        try
        {
            byte[] buffer = new byte[bytePerSecondLimit];
            int bytesRead = inputStream.read(buffer);
            if(bytesRead != -1){
                outputStream.write(buffer, 0, bytesRead);
            } else {
                outputStream.close();
                inputStream.close();
                timer.cancel();
            }
            downloadedLength += bytesRead;
            System.out.println (bytesRead + " bytes per second. "+ NumberFormat.getPercentInstance ().format ( downloadedLength/contentLength )+" completed...");
        }
        catch ( IOException e )
        {
            e.printStackTrace();
            throw new RuntimeException ( "Error During Download..." , e.getCause () );
        }
    }

    private InputStream createInputStreamFromUrl ( String fileUrl ) throws IOException
    {
        URL url = new URL ( fileUrl );
        HttpURLConnection httpConn = (HttpURLConnection) url.openConnection ();
        int responseCode = httpConn.getResponseCode ();

        // always check HTTP response code first
        if ( responseCode == HttpURLConnection.HTTP_OK )
        {
            String fileName = "";
            String disposition = httpConn
                    .getHeaderField ( "Content-Disposition" );
            String contentType = httpConn.getContentType ();
            contentLength = httpConn.getContentLength ();

            if ( disposition != null )
            {
                // extracts file name from header field
                int index = disposition.indexOf ( "filename=" );
                if ( index > 0 )
                {
                    fileName = disposition.substring ( index + 10 , disposition.length () - 1 );
                }
            }
            else
            {
                // extracts file name from URL
                fileName = fileUrl.substring ( fileUrl.lastIndexOf ( "/" ) + 1 , fileUrl.length () );
            }

            System.out.println ( "Content-Type = " + contentType );
            System.out.println ( "Content-Disposition = " + disposition );
            System.out.println ( "Content-Length = " + contentLength );
            System.out.println ( "fileName = " + fileName );

            // opens input stream from the HTTP connection
            InputStream inputStream = httpConn.getInputStream ();

            return inputStream;
        }

        return null;
    }

    /**
     * @return the bytePerSecondLimit
     */
    public int getBytePerSecondLimit ()
    {
        return bytePerSecondLimit;
    }

    /**
     * @param bytePerSecondLimit the bytePerSecondLimit to set
     */
    public void setBytePerSecondLimit ( int bytePerSecondLimit )
    {
        this.bytePerSecondLimit = bytePerSecondLimit;
    }

    public static void main ( String[] args ) throws IOException
    {
        DownloaderWithLimit d = new DownloaderWithLimit ( "https://download.mozilla.org/?product=firefox-46.0.1-SSL&os=win64&lang=en-US" , "c:/firefox-46.0.1_x64.exe" , 10240);//10Kb/s
        d.start ();
    }
}
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.NumberFormat;
import java.util.Timer;
import java.util.TimerTask;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;


public class FtpDownloaderWithLimit extends TimerTask
{
    private InputStream inputStream;
    private OutputStream outputStream;

    private int bytePerSecondLimit;
    private Timer timer;
    private float contentLength;
    private float downloadedLength;
    private FTPClient ftpClient;

    public FtpDownloaderWithLimit (String ftpServer, int port, String username, String password, String srcFileRelativePath, String destFileFullPath, int bytePerSecondLimit) throws IOException
    {
        this.bytePerSecondLimit = bytePerSecondLimit;
        //
        inputStream = createInputStreamFromUrl ( ftpServer, port, username, password, srcFileRelativePath );
        outputStream = new FileOutputStream ( new File ( destFileFullPath ) );
    }

    public void start(){
        timer = new Timer();
        timer.scheduleAtFixedRate(this, 1000, 1000);
    }

    public void run () 
    {
        try
        {
            byte[] buffer = new byte[bytePerSecondLimit];
            int bytesRead = inputStream.read(buffer);
            if(bytesRead != -1){
                outputStream.write(buffer, 0, bytesRead);
            } else {
                boolean success = ftpClient.completePendingCommand();
                if (success) {
                    System.out.println("File #2 has been downloaded successfully.");
                }
                outputStream.close();
                inputStream.close();
                timer.cancel();
            }
            downloadedLength += bytesRead;
            System.out.println (bytesRead + " bytes per second. "+ NumberFormat.getPercentInstance ().format ( downloadedLength/contentLength )+" completed...");
        }
        catch ( IOException e )
        {
            e.printStackTrace();
            throw new RuntimeException ( "Error During Download..." , e.getCause () );
        }
    }

    private InputStream createInputStreamFromUrl(String ftpServer, int port,
            String username, String password, String srcFileRelativePath) throws IOException{

        ftpClient = new FTPClient();
        ftpClient.connect(ftpServer, port);
        ftpClient.login(username, password);
        ftpClient.enterLocalPassiveMode();
        ftpClient.setFileType(FTP.BINARY_FILE_TYPE);

        InputStream inputStream = ftpClient.retrieveFileStream(srcFileRelativePath);

        return inputStream;
    }

    /**
     * @return the bytePerSecondLimit
     */
    public int getBytePerSecondLimit ()
    {
        return bytePerSecondLimit;
    }

    /**
     * @param bytePerSecondLimit the bytePerSecondLimit to set
     */
    public void setBytePerSecondLimit ( int bytePerSecondLimit )
    {
        this.bytePerSecondLimit = bytePerSecondLimit;
    }

    public static void main ( String[] args ) throws IOException
    {
        FtpDownloaderWithLimit d = new FtpDownloaderWithLimit ( "www.myserver.com" , 9111 /*sample port*/, "USERNAME", "PASSWORD", "/My/File/To/Downlaod.xxx", "c:/your-path-to-dest-file" , 10240);//10Kb/s
        d.start ();
    }

}
具有利率限制的FTP样本如下:

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.NumberFormat;
import java.util.Timer;
import java.util.TimerTask;

public class DownloaderWithLimit extends TimerTask
{
    private InputStream inputStream;
    private OutputStream outputStream;

    private int bytePerSecondLimit;
    private Timer timer;
    private float contentLength;
    private float downloadedLength;

    public DownloaderWithLimit (String urlToDownload, String destFileFullPath, int bytePerSecondLimit) throws IOException
    {
        this.bytePerSecondLimit = bytePerSecondLimit;
        //
        inputStream = createInputStreamFromUrl ( urlToDownload );
        outputStream = new FileOutputStream ( new File ( destFileFullPath ) );
    }

    public void start(){
        timer = new Timer();
        timer.scheduleAtFixedRate(this, 1000, 1000);
    }

    public void run () 
    {
        try
        {
            byte[] buffer = new byte[bytePerSecondLimit];
            int bytesRead = inputStream.read(buffer);
            if(bytesRead != -1){
                outputStream.write(buffer, 0, bytesRead);
            } else {
                outputStream.close();
                inputStream.close();
                timer.cancel();
            }
            downloadedLength += bytesRead;
            System.out.println (bytesRead + " bytes per second. "+ NumberFormat.getPercentInstance ().format ( downloadedLength/contentLength )+" completed...");
        }
        catch ( IOException e )
        {
            e.printStackTrace();
            throw new RuntimeException ( "Error During Download..." , e.getCause () );
        }
    }

    private InputStream createInputStreamFromUrl ( String fileUrl ) throws IOException
    {
        URL url = new URL ( fileUrl );
        HttpURLConnection httpConn = (HttpURLConnection) url.openConnection ();
        int responseCode = httpConn.getResponseCode ();

        // always check HTTP response code first
        if ( responseCode == HttpURLConnection.HTTP_OK )
        {
            String fileName = "";
            String disposition = httpConn
                    .getHeaderField ( "Content-Disposition" );
            String contentType = httpConn.getContentType ();
            contentLength = httpConn.getContentLength ();

            if ( disposition != null )
            {
                // extracts file name from header field
                int index = disposition.indexOf ( "filename=" );
                if ( index > 0 )
                {
                    fileName = disposition.substring ( index + 10 , disposition.length () - 1 );
                }
            }
            else
            {
                // extracts file name from URL
                fileName = fileUrl.substring ( fileUrl.lastIndexOf ( "/" ) + 1 , fileUrl.length () );
            }

            System.out.println ( "Content-Type = " + contentType );
            System.out.println ( "Content-Disposition = " + disposition );
            System.out.println ( "Content-Length = " + contentLength );
            System.out.println ( "fileName = " + fileName );

            // opens input stream from the HTTP connection
            InputStream inputStream = httpConn.getInputStream ();

            return inputStream;
        }

        return null;
    }

    /**
     * @return the bytePerSecondLimit
     */
    public int getBytePerSecondLimit ()
    {
        return bytePerSecondLimit;
    }

    /**
     * @param bytePerSecondLimit the bytePerSecondLimit to set
     */
    public void setBytePerSecondLimit ( int bytePerSecondLimit )
    {
        this.bytePerSecondLimit = bytePerSecondLimit;
    }

    public static void main ( String[] args ) throws IOException
    {
        DownloaderWithLimit d = new DownloaderWithLimit ( "https://download.mozilla.org/?product=firefox-46.0.1-SSL&os=win64&lang=en-US" , "c:/firefox-46.0.1_x64.exe" , 10240);//10Kb/s
        d.start ();
    }
}
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.NumberFormat;
import java.util.Timer;
import java.util.TimerTask;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;


public class FtpDownloaderWithLimit extends TimerTask
{
    private InputStream inputStream;
    private OutputStream outputStream;

    private int bytePerSecondLimit;
    private Timer timer;
    private float contentLength;
    private float downloadedLength;
    private FTPClient ftpClient;

    public FtpDownloaderWithLimit (String ftpServer, int port, String username, String password, String srcFileRelativePath, String destFileFullPath, int bytePerSecondLimit) throws IOException
    {
        this.bytePerSecondLimit = bytePerSecondLimit;
        //
        inputStream = createInputStreamFromUrl ( ftpServer, port, username, password, srcFileRelativePath );
        outputStream = new FileOutputStream ( new File ( destFileFullPath ) );
    }

    public void start(){
        timer = new Timer();
        timer.scheduleAtFixedRate(this, 1000, 1000);
    }

    public void run () 
    {
        try
        {
            byte[] buffer = new byte[bytePerSecondLimit];
            int bytesRead = inputStream.read(buffer);
            if(bytesRead != -1){
                outputStream.write(buffer, 0, bytesRead);
            } else {
                boolean success = ftpClient.completePendingCommand();
                if (success) {
                    System.out.println("File #2 has been downloaded successfully.");
                }
                outputStream.close();
                inputStream.close();
                timer.cancel();
            }
            downloadedLength += bytesRead;
            System.out.println (bytesRead + " bytes per second. "+ NumberFormat.getPercentInstance ().format ( downloadedLength/contentLength )+" completed...");
        }
        catch ( IOException e )
        {
            e.printStackTrace();
            throw new RuntimeException ( "Error During Download..." , e.getCause () );
        }
    }

    private InputStream createInputStreamFromUrl(String ftpServer, int port,
            String username, String password, String srcFileRelativePath) throws IOException{

        ftpClient = new FTPClient();
        ftpClient.connect(ftpServer, port);
        ftpClient.login(username, password);
        ftpClient.enterLocalPassiveMode();
        ftpClient.setFileType(FTP.BINARY_FILE_TYPE);

        InputStream inputStream = ftpClient.retrieveFileStream(srcFileRelativePath);

        return inputStream;
    }

    /**
     * @return the bytePerSecondLimit
     */
    public int getBytePerSecondLimit ()
    {
        return bytePerSecondLimit;
    }

    /**
     * @param bytePerSecondLimit the bytePerSecondLimit to set
     */
    public void setBytePerSecondLimit ( int bytePerSecondLimit )
    {
        this.bytePerSecondLimit = bytePerSecondLimit;
    }

    public static void main ( String[] args ) throws IOException
    {
        FtpDownloaderWithLimit d = new FtpDownloaderWithLimit ( "www.myserver.com" , 9111 /*sample port*/, "USERNAME", "PASSWORD", "/My/File/To/Downlaod.xxx", "c:/your-path-to-dest-file" , 10240);//10Kb/s
        d.start ();
    }

}
希望这会有所帮助。

您可以尝试读取任何InputStream的数据(字节[]b,int off,int len)。len是读取的最大字节数。 off是流开始插入的位置,b是流写入的字节[] 因此,如果您只想读取1000字节,可以尝试使用

int whereYouWantToStartInserting = 0;
int maximumOfBytes;
read(buffer,whereYouWantToStartInserting,maximumOfBytes);
我希望这段代码可以帮助您。

您可以尝试读取任何InputStream的字节(字节[]b,int off,int len)。len是读取的最大字节数。 off是流开始插入的位置,b是流写入的字节[] 因此,如果您只想读取1000字节,可以尝试使用

int whereYouWantToStartInserting = 0;
int maximumOfBytes;
read(buffer,whereYouWantToStartInserting,maximumOfBytes);

我希望这段代码可以帮助您。

我不会重写它,而是修饰它-看看Reader、InputStreamReader和BufferedReader等类,看看它们是如何协同工作的。为什么要限制文件的读取速率?不管你想做什么,都可能有更好的方法。@PeterLawrey实际上是这样限制下载速度的。我不认为
InputStreamReader
是处理二进制文件的正确方法。你对下载速度没有任何疑问。不清楚你在问什么。你还应该看到我不会覆盖它,而是修饰它-看看Reader、InputStreamReader和BufferedReader等类,看看它们是如何协同工作的。为什么要限制文件的读取速率?不管你想做什么,都可能有更好的方法。@PeterLawrey实际上是这样限制下载速度的。我不认为
InputStreamReader
是处理二进制文件的正确方法。你对下载速度没有任何疑问。不清楚你在问什么。你也应该看看谢谢你的例子<代码>番石榴看起来更干净是的。然而,它似乎在限制输出流。假设我有最大10KB的下载限制,我决定设置5KB的限制。似乎这将只使用10 kb的限制,并以5 kb/s的速度写入文件,这不是我真正想要的。一旦文件被下载,它就可以以所需的速度写入,我的目标是不限制传入文件的下载/读取速度。“这是有效的方法吗?”复仇者我不知道你为什么这么说。您的代码读取、写入和循环。此解决方案在写入和循环之间阻塞,因此下一次读取必须等待。感谢您的示例<代码>番石榴看起来更干净是的。然而,它似乎在限制输出流。假设我有最大10KB的下载限制,我决定设置5KB的限制。这似乎只需要使用10KB的限制和wr