gpt4 book ai didi

java - 限制输入流

转载 作者:行者123 更新时间:2023-11-29 10:10:35 30 4
gpt4 key购买 nike

我是 Java 的新手。我编写了一个通过 Internet 下载特定文件的 Swing 应用程序。

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

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

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

我使用 this HTTP 下载和 this 的示例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();
}
}

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 个输入流的下载速率,以便在从远程位置获取这些文件时下载速度受到限制。

如果您能给我一个带有简短解释的示例,我将不胜感激。

最佳答案

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

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_SIZE 不是 MAX_BYTES_PER_SECOND 的一个因素,并且您对节流率很在意,您可能需要使用 read() 接受偏移量和限制参数以准确读取正确数量的重载。


为了更简洁的解决方案,您可以使用 Guava 的 RateLimiter:

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

关于java - 限制输入流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37496058/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com