使用nio多线程下载网络文件实例
生活随笔
收集整理的這篇文章主要介紹了
使用nio多线程下载网络文件实例
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
代碼:
import io.github.viscent.mtia.util.Debug; import io.github.viscent.mtia.util.Tools;import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.nio.ByteBuffer; import java.nio.channels.Channels;import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel;public class FileDownloaderApp {public static void main(String[] args) {String[]pics =new String[]{"https://dlqn.aoscdn.com/beecut-setup-pin.exe","https://scpic.chinaz.net/files/pic/pic9/202112/apic37306.jpg"};Thread downloaderThread = null;for (String url : pics) {// 創建文件下載器線程downloaderThread = new Thread(new FileDownloader(url));// 啟動文件下載器線程downloaderThread.start();}}// 文件下載器線程類,拓展runnable接口static class FileDownloader implements Runnable {private final String fileURL;public FileDownloader(String fileURL) {this.fileURL = fileURL;} //在run方法中獲取文件夾路徑,調用下載文件的方法進行下載@Overridepublic void run() {Debug.info("Downloading from " + fileURL);String fileBaseName = fileURL.substring(fileURL.lastIndexOf('/') + 1);try {URL url = new URL(fileURL);String localFileName = System.getProperty("java.io.tmpdir")//自己電腦系統的臨時文件夾路徑位置+ fileBaseName;Debug.info("Saving to: " + localFileName);downloadFile(url, new FileOutputStream(localFileName), 1024);} catch (Exception e) {e.printStackTrace();}Debug.info("Done downloading from " + fileURL);}// 從指定的URL下載文件,并將其保存到指定的輸出流中,在這里使用了nio的 ReadableByteChannel和WritableByteChannel 用方法 buf.flip(); // outChannel.write(buf);從給定的緩沖區將字節序列寫入此通道private void downloadFile(URL url, OutputStream outputStream, int bufSize)throws MalformedURLException, IOException {// 建立HTTP連接final HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();httpConn.setRequestMethod("GET");ReadableByteChannel inChannel = null;WritableByteChannel outChannel = null;try {// 獲取HTTP響應碼int responseCode = httpConn.getResponseCode();// HTTP響應非正常:響應碼不為2開頭if (2 != responseCode / 100) {throw new IOException("Error: HTTP " + responseCode);}if (0 == httpConn.getContentLength()) {Debug.info("Nothing to be downloaded " + fileURL);return;}inChannel = Channels.newChannel(new BufferedInputStream(httpConn.getInputStream()));outChannel = Channels.newChannel(new BufferedOutputStream(outputStream));ByteBuffer buf = ByteBuffer.allocate(bufSize);while (-1 != inChannel.read(buf)) {buf.flip();outChannel.write(buf);buf.clear();}} finally {// 關閉指定的Channel以及HttpURLConnectionTools.silentClose(inChannel, outChannel);httpConn.disconnect();}}// downloadFile結束}// FileDownloader結束 }其中Debug為自定義的工具類
import java.io.PrintStream; import java.text.SimpleDateFormat; import java.util.Date;public class Debug {private static ThreadLocal<SimpleDateFormat> sdfWrapper = new ThreadLocal<SimpleDateFormat>() {@Overrideprotected SimpleDateFormat initialValue() {return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");}};enum Label {INFO("INFO"),ERR("ERROR");String name;Label(String name) {this.name = name;}public String getName() {return name;}}// public static void info(String message) {// printf(Label.INFO, "%s", message);// }public static void info(String format, Object... args) {printf(Label.INFO, format, args);}public static void info(boolean message) {info("%s", message);}public static void info(int message) {info("%d", message);}public static void error(String message, Object... args) {printf(Label.ERR, message, args);}public static void printf(Label label, String format, Object... args) {SimpleDateFormat sdf = sdfWrapper.get();@SuppressWarnings("resource")final PrintStream ps = label == Label.INFO ? System.out : System.err;ps.printf('[' + sdf.format(new Date()) + "][" + label.getName()+ "]["+ Thread.currentThread().getName() + "]:" + format + " %n", args);} }其中tools關閉文件的方法:
public final class Tools {private static final Random rnd = new Random();private static final Logger LOGGER = Logger.getAnonymousLogger();public static void startAndWaitTerminated(Thread... threads)throws InterruptedException {if (null == threads) {throw new IllegalArgumentException("threads is null!");}for (Thread t : threads) {t.start();}for (Thread t : threads) {t.join();}}public static void startAndWaitTerminated(Iterable<Thread> threads)throws InterruptedException {if (null == threads) {throw new IllegalArgumentException("threads is null!");}for (Thread t : threads) {t.start();}for (Thread t : threads) {t.join();}}public static void randomPause(int maxPauseTime) {int sleepTime = rnd.nextInt(maxPauseTime);try {Thread.sleep(sleepTime);} catch (InterruptedException e) {Thread.currentThread().interrupt();}}public static void randomPause(int maxPauseTime, int minPauseTime) {int sleepTime = maxPauseTime == minPauseTime ? minPauseTime : rnd.nextInt(maxPauseTime - minPauseTime) + minPauseTime;try {Thread.sleep(sleepTime);} catch (InterruptedException e) {Thread.currentThread().interrupt();}}public static void silentClose(Closeable... closeable) {if (null == closeable) {return;}for (Closeable c : closeable) {if (null == c) {continue;}try {c.close();} catch (Exception ignored) {}}}public static void split(String str, String[] result, char delimeter) {int partsCount = result.length;int posOfDelimeter;int fromIndex = 0;String recordField;int i = 0;while (i < partsCount) {posOfDelimeter = str.indexOf(delimeter, fromIndex);if (-1 == posOfDelimeter) {recordField = str.substring(fromIndex);result[i] = recordField;break;}recordField = str.substring(fromIndex, posOfDelimeter);result[i] = recordField;i++;fromIndex = posOfDelimeter + 1;}}public static void log(String message) {LOGGER.log(Level.INFO, message);}public static String md5sum(final InputStream in) throws NoSuchAlgorithmException, IOException {MessageDigest md = MessageDigest.getInstance("MD5");byte[] buf = new byte[1024];try (DigestInputStream dis = new DigestInputStream(in, md)) {while (-1 != dis.read(buf)){};}byte[] digest = md.digest();BigInteger bigInt = new BigInteger(1, digest);String checkSum = bigInt.toString(16);while (checkSum.length() < 32) {checkSum = "0" + checkSum;}return checkSum;}public static String md5sum(final File file) throws NoSuchAlgorithmException, IOException {return md5sum(new BufferedInputStream(new FileInputStream(file)));}public static void delayedAction(String prompt, Runnable action, int delay/* seconds */) {Debug.info("%s in %d seconds.", prompt, delay);try {Thread.sleep(delay * 1000);} catch (InterruptedException ignored) {}action.run();}public static Object newInstanceOf(String className) throws InstantiationException,IllegalAccessException, ClassNotFoundException {return Class.forName(className).newInstance();}}結果:
可以看到這里開了兩個線程用于下載上面的兩個鏈接
文件夾下面可以看到剛剛自己下載好的兩個文件:
打開圖片也可以看到完整的圖片顯示:
總結
以上是生活随笔為你收集整理的使用nio多线程下载网络文件实例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: springboot整合kafka和ne
- 下一篇: zookeeper分布式锁代码实例