2016-05-28 11 views
1

私はJavaを使い慣れていません。私はインターネット上で特定のファイルをダウンロードするSwingアプリケーションを書いた。制限入力ストリーム

InputStreamは、n(10240バイトと言えますが、これは変更可能です)バイト/秒を制限することです。

ファイル全体が読み込まれると、それは、そのようなC:\Downloads\

としてローカルディレクトリにファイルを保存する必要があり、私は私がInputStreamに拡張するクラスを作成し、そのメソッドをオーバーライドする必要があります推測しているが、私は正確ではありませんよ私の目標を達成するための方法と方法

HTTPダウンロードの場合はthis、FTPの場合はthisの例を使用します。

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(); 
    } 
} 

FTP例。私が好きな何

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(); 
      } 
     } 
    } 
} 

は、これらの2入力のダウンロード速度は、遠隔地からこれらのファイルを取得しながら、そのダウンロード速度が制限されるストリームを制限することです。

簡単な説明で私に例を示すことができたら本当にありがたいです。

+2

私はそれを無効にするのではなく、それを飾ります.Reader、InputStreamReader、BufferedReaderなどのクラスを見て、どのように連携しているかを確認してください。 – stuXnet

+1

ファイルを読み取る速度を制限する理由を教えてください。あなたが何をしようとしている場合でも、より良い方法がある可能性があります。 –

+0

@PeterLawrey実際には、このようにダウンロード速度を制限しようとしています。私は 'InputStreamReader'がバイナリファイルを扱う正しい方法だとは思わない。 – Revenant

答えて

4

これは少し基本的なことですが、あなたが求めていることを実行する必要があります(テストしませんでした)。

int bytesReadSinceSleep = 0; 
long lastSleepTime = System.currentTimeMillis(); 

while ((bytesRead = inputStream.read(buffer)) != -1) { 
    outputStream.write(buffer, 0, bytesRead); 

    // increment bytes read this second 
    bytesReadSinceSleep += bytesRead; 

    // if we've passed the throttling point, sleep for the remainder of the second 
    if (bytesReadSinceSleep >= MAX_BYTES_PER_SECOND) { 

     // calculate time elapsed since last sleep 
     long timeElapsed = System.currentTimeMillis() - lastSleepTime; 

     // sleep for the remainder of 1 second (if there is a remainder) 
     Thread.sleep(Math.max(1000 - timeElapsed, 0)); 

     // reset byte count 
     bytesReadSinceSleep = 0; 

     // reset sleep time 
     lastSleepTime = System.currentTimeMillis(); 
    } 
} 

BUFFER_SIZEMAX_BYTES_PER_SECONDの要因ではない、とあなたはスロットル率について特定している場合は、正確に適切な量を読み取るためにread()オフセット受け入れ過負荷と制限パラメータを使用することをお勧めします。クリーナーソリューションのために


、あなたはグアバのRateLimiterを使用することができます。

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

ありがとうございます。グアバはきれいにはいそうです。しかし、それは 'outputStream'を制限しているようです。だから私は最大10kbのダウンロード制限があり、私は5kbの制限を入れることに決めたとしよう。これは、これはちょうど10キロバイトの制限を使用し、私が本当に望むものではない5キロバイト/秒でファイルを書くようだ。ファイルがダウンロードされると、それは必要なだけ速く書くことができます。私の目的は、実際に着信ファイルのダウンロード/読み取り速度を制限することではありません。これは効率的な方法でしょうか? – Revenant

+0

@Revenantなぜあなたはそれを言っているのか分かりません。コードの読み取り、書き込み、およびループ。このソリューションは、書き込みとループの間をブロックするため、次の読み取りは待機する必要があります。 – shmosel

3

あなたが実際に代わりInputStreamを拡張するjava.util.TimerTaskを拡張することができます。その後、java.util.Timerを使用すると、ファイル全体がダウンロードされるまで1秒に1回実行されるタスクをスケジュールできます。つまり、1秒にダウンロードしたいバイト数を定義するだけです。場合によっては、ダウンロードが(ネットワーク遅延などの理由により)あなたが提供した制限を下回る場合もありますが、これは競合ではありません。あらゆる状況において、あなたのダウンロード速度はあなたが提供した制限を下回るからです。さらに、ダウンロード処理中であっても、いつでもダウンロード速度を変更することができます。

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(); 
    } 
} 

そして、レート制限付きFTPサンプルは以下の通りです:HTTP/HTTPS実装のサンプルは以下の通りである、これは参考になる

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(); 
    } 

} 

希望。

+0

ありがとうございます。私はできるだけ早くそれをテストします。私は同様にFTPファイルのためにそれを修正する必要があります。 – Revenant

+0

OKです。FTPに変更するのは簡単で、 'createInputStreamFromUrl'メソッドを変更するだけです。この回答があなたの問題を解決した場合、それを受け入れることができます。 – STaefi

+0

@Revenant:こんにちは私は 'ftp'サンプルを追加する答えを更新しました。 – STaefi

1

任意のInputStreamのread(byte [] b、int off、int len)を試すことができます。lenは読み込まれる最大バイト数です。 オフはストリームが挿入aとbを開始する位置であるバイトが[]するストリームが、私はこのコードはあなたを助けるかもしれない願っていますあなたが唯一の1000バイトを読みたい場合は、

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

を使用して試みることができるので、 を書き込みしています。

関連する問題