用 Java 下载文件。多线程,这有效吗?

2023-12-07

首先,每个人都需要知道我对 Java 编码还比较陌生。更准确地说,我对面向对象编程完全陌生。


对于这个问题。

我正在尝试创建一个下载类来更新进度条以显示其进度。可能还有我决定将来更新的其他内容。

目前的问题是,在我看来,这不应该起作用。我可以在“main”方法上做任何我想做的事情,并且 GUI 仍然响应灵敏且快速。根据我过去的编程经验,除非我线程化 GUI,否则这是不可能的。为什么是这样?

既然可行,那么这样做可以吗?


主类

package atomicElectronics;

import java.io.IOException;

import atomicElectronics.physical.AtomFrame;
import atomicElectronics.utility.Download;

public class Initial {

    static AtomFrame atomLauncher;

    public static void main(String[] args) {

        atomLauncher = new AtomFrame();
        atomLauncher.start();

        System.out.println(Integer.MAX_VALUE);

        Download theDownload = new Download();
        theDownload.fileProgressBar(atomLauncher.progressBar);
        try {
            theDownload.exicute("http://download.videolan.org/pub/videolan/vlc/last/win64/vlc-2.1.3-win64.exe", "C:\\Users\\TrinaryAtom\\AppData\\Roaming");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        // TODO Add Download Methods
        // theDownload.updateBarTotal(JProgressBar);
        // theDownload.updateLabelSpeed(String);
        // theDownload.updateLabelTotal(String);
        // theDownload.addFile(File);
        // theDownload.addFiles(Files);
    }

}

类 AtomFrame

package atomicElectronics.physical;

import javax.swing.JFrame;
import java.awt.FlowLayout;
import javax.swing.JProgressBar;

public class AtomFrame extends JFrame{

    public JProgressBar progressBar;

    private static final long serialVersionUID = 4010489530693307355L;

    public static void main(String[] args){
        AtomFrame testFrame = new AtomFrame();
        testFrame.start();
    }

    public AtomFrame(){
        initializeComponents();
    }

    public void initializeComponents(){
        this.setSize(400, 400);
        this.setLocationRelativeTo(null);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setTitle("Atom Launcher");
        this.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));

        progressBar = new JProgressBar();
        this.add(progressBar);

        //this.pack();
    }

    public void start() {
        this.setVisible(true);
    }

    public void close() {
        this.dispose();
    }
}

课程下载

package atomicElectronics.utility;

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

import javax.swing.JProgressBar;

public class Download {

    private static final int BUFFER_SIZE = 4096;
    private JProgressBar fileProgressBar;

    public Download() {
    }

    public void fileProgressBar(JProgressBar fileBar) {
        fileProgressBar = fileBar;
    }

    public void exicute(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();
            double contentLength = httpConn.getContentLength();

            if (disposition != null) {
                // extracts file name from header field
                int index = disposition.indexOf("filename=");
                if (index > 0) {


          fileName = disposition.substring(index + 9,
                        disposition.length());
            }
        } 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);

        double totalRead = 0;
        int bytesRead = -1;
        byte[] buffer = new byte[BUFFER_SIZE];
        while ((bytesRead = inputStream.read(buffer)) != -1) {
            outputStream.write(buffer, 0, bytesRead);
            totalRead += bytesRead;
            System.out.println((totalRead / contentLength) * 100);
            fileProgressBar.setValue((int)((totalRead / contentLength) * 100));
        }

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

        System.out.println("File downloaded");
    } else {
        System.out.println("No file to download. Server replied HTTP code: " + responseCode);
    }
    httpConn.disconnect();

}

}


建议:

  • 使用 SwingWorker 来完成后台线程工作。
  • 在 SwingWorker 内部,通过以下方式设置其进度“bound”属性setProgress(int progress)。该值应介于 1 和 100 之间。
  • 不要让您的 SwingWorker/文件下载器保存 JProgressBar 或任何 Swing 组件。
  • 将 PropertyChangeListener 添加到 SwingWorker 并监视进度属性的更改。
  • 切勿将您的 Swing 字段(或大多数和所有字段)公开。限制访问,而是通过方法更改对象状态。
  • 阅读教程Swing 中的并发了解必要的详细信息。

例如,下面的代码是一个总体简化,不下载任何文件,但应该可以让您了解:

import java.awt.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Random;

import javax.swing.*;

public class Initial {

   static AtomFrame atomLauncher;

   public static void main(String[] args) {

      atomLauncher = new AtomFrame();
      atomLauncher.start();

      System.out.println(Integer.MAX_VALUE);

      final Download theDownload = new Download();
      theDownload.addPropertyChangeListener(new PropertyChangeListener() {

         @Override
         public void propertyChange(PropertyChangeEvent pcEvt) {
            if ("progress".equals(pcEvt.getPropertyName())) {
               int progress = theDownload.getProgress();
               atomLauncher.setProgress(progress);
            }
         }
      });

      theDownload.execute();
   }

}

class AtomFrame extends JFrame {

   // ********* should be private!
   private JProgressBar progressBar;

   private static final long serialVersionUID = 4010489530693307355L;

   public static void main(String[] args) {
      AtomFrame testFrame = new AtomFrame();
      testFrame.start();
   }

   public void setProgress(int progress) {
      progressBar.setValue(progress);
   }

   public AtomFrame() {
      initializeComponents();
   }

   public void initializeComponents() {
      this.setSize(400, 400);
      this.setLocationRelativeTo(null);
      this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      this.setTitle("Atom Launcher");
      this.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));

      progressBar = new JProgressBar();
      this.add(progressBar);

      // this.pack();
   }

   public void start() {
      this.setVisible(true);
   }

   public void close() {
      this.dispose();
   }
}

class Download extends SwingWorker<Void, Void> {
   private static final long SLEEP_TIME = 300;
   private Random random = new Random();

   @Override
   protected Void doInBackground() throws Exception {
      int myProgress = 0;
      while (myProgress < 100) {
         myProgress += random.nextInt(10);
         setProgress(myProgress);
         try {
            Thread.sleep(SLEEP_TIME);
         } catch (InterruptedException e) {}
      }
      return null;
   }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

用 Java 下载文件。多线程,这有效吗? 的相关文章

  • 如何在 Java 中解析这样的 URI

    我正在尝试解析以下 URI http translate google com zh CN en 你 http translate google com zh CN 7Cen 7C E4 BD A0 但收到此错误消息 java net UR
  • 您无权访问此服务器上的 /schema/beans/spring-beans-3.1.xsd

    我在我的一个应用程序中使用 spring 框架 到目前为止一切正常 但是今天早上 当我尝试运行我的应用程序时 它抛出错误 因为无法初始化 spring 框架 因此 我尝试在浏览器中加载 xsd 文件 但徒劳无功 因为它向我显示了禁止的页面
  • 进入活动后设置自定义对话框

    我的列表活动由多行组成 每行打开活动包含文本和两个按钮 其中一个打开无限图库 另一个打开对话框 每个对话框都有不同的字符串 我有 20 行 所以我添加了 20 次对话框 这是多余的 而且它工作正常 但我认为有比我所做的更好的方法 任何获得它
  • 如何在 bash 脚本中使用并行编程/多线程?

    这是我的脚本 bin bash script to loop through directories to merge fastq files sourcedir path to source destdir path to dest fo
  • 如何使用 spring data jpa 调用数据库函数?

    我想从 Spring Boot 应用程序调用数据库函数 该函数将返回解密的值 是否可以使用spring data jpa调用数据库函数 如果可以的话怎么办 如果无法使用 spring data jpa 是否有其他方法可以从 Spring B
  • 将 Scala 库转换为 DLL (.NET)

    我正在尝试从 scala 类创建一个 Dll 我将 IntelliJ 与 SBT 一起使用 我已经找到了一种使用 ikvm converter 将 jar 文件转换为 Dll 的方法 现在的问题是 当我在 SBT 下使用 package 从
  • Java 中 float 和 double 基元的比较

    我发现了Java的一个奇怪的角落 我觉得很奇怪 double dd 3 5 float ff 3 5f System out println dd ff 输出 正确 double dd 3 2 float ff 3 2f System ou
  • gwt rpc 中的会话 ID cookie

    假设我正在滚动自己的会话代码 那么在 java 中生成唯一且安全的会话 id cookie 的正确方法是什么 我不应该自己推出而是使用已经标准化的东西吗 我正在使用 gwt 和 google app engine 平台 如何使会话在浏览器
  • IBM Websphere JPA 配置 - 如何更新 persistence.xml

    我是 EJB 3 和 JPA 的新手 我在应用程序服务器中创建了一个数据源 它是jdbc AppDataSource 默认持久性提供程序保留为com ibm websphere persistence PersistenceProvider
  • 使用超类创建构建器时,父类无法返回子类的实例[重复]

    这个问题在这里已经有答案了 如果我使用构建器模式来配置新对象 我可能有两个类 例如Game and HockeyGame 如下所示 当我想创建一个新的HockeyGame 我得到它的构建器并开始调用方法来根据需要配置对象 我遇到的问题显示在
  • JSF中直接更改URL来限制用户访问页面

    我的应用程序中有两种用户 客户和卖家 我正在使用一个PhaseListener在JSF中防止用户在未登录的情况下访问页面 但在登录后我不知道如何防止用户更改地址栏中的URL并访问他也不允许的页面 例如 阻止客户访问卖家页面 有谁知道我如何防
  • Java字符串模式识别

    我有一个大约一千个字符长的字符串 由 L T 和 A 组成 我很确定其中有一个简单的模式 我想知道是否有任何快速简便的方法可以找到它 该字符串会发生变化 因此这不仅仅是一次性的 我正在寻找的模式例如如果字符串是 LLLLLLLLAATAAL
  • Java Swing:为什么必须调整框架大小,以便可以显示已添加的组件

    我有一个简单的 Swing GUI 不仅如此 我编写的所有 swing GUI 运行它时 除了空白屏幕之外 它不会显示任何内容 直到我调整主框架的大小 因此每个组件都已重新绘制 我可以显示它们 这是我的简单代码 public static
  • 为什么在 GWT(或任何 Web 应用程序)中使用命令模式?

    根据这个视频 7 50 Google 建议在其请求处理 API 之上使用命令模式 还有一个看起来很有帮助的项目gwt 调度 http code google com p gwt dispatch 实现该模式 根据 gwt 调度我需要为每个命
  • 如何在“mvn clean install”期间在 SpringBootTest 运行中禁用 ch.qos.logback 自己的 INFO 消息

    在与 RasmusFaber 获得最多支持的答案的作者 讨论后使用布局时如何防止 logback 在每个日志的开头输出自己的状态 https stackoverflow com q 3257154 2886891 我决定创建一个新问题 因为
  • 将自定义方法映射器映射到 Mapstruct

    我正在创建一个 poc 以便在我未来的项目中使用 Mapstruct 现在我有一个问题如何将自定义方法映射到特殊目标 例如我有以下接口映射器 Mapper public interface ItemMapper static ItemMap
  • 将 OraclePreparedStatement 与 DBCP 连接结合使用

    我正在尝试使用 dbcp 框架为我的 oracle 服务器创建一个连接池 我用过这个tutorial http web archive org web 20120615100115 http www freshblurbs com 80 j
  • 在java正则表达式中获取组名

    我正在尝试接收模式和字符串并返回组名称 gt 匹配结果的映射 Example
  • 重写等于方法

    新手问题在这里 因此 在我的大学作业中 我必须为我创建的新类重写对象类 equals 方法 新的类是 Product 每个产品都有一个唯一的 id 属性 这就是我重写它的方式 Override public boolean equals O
  • 在使用 stop_token 等待条件变量_any 时是否需要拥有锁来请求停止?

    在等待条件变量时 更改谓词状态的线程必须拥有锁 因此在唤醒期间不会错过更新 根据文档 这是必要的 即使在使用原子变量时也是如此 不过我不确定是否request stop 已经正确处理了 那么问题是 这两个选项中哪一个是正确且符合标准的呢 j

随机推荐

  • 这个片段的复杂度是 O(log^2(n)) 吗?

    如果不是 那么复杂性会是多少 谢谢 public static int f int n int x for int i n i gt 0 i 2 for int j 0 j lt i j x j Assume this operation
  • 在 gitolite 中重新生成authorized_keys 文件?

    是否可以 我的authorized keys 文件被擦除 更新 gitolite 管理规则仅附加到文件 是否可以根据 gitolite 配置重新生成整个文件 编辑 找到了 gitolite trigger POST COMPILE 使用 g
  • Visual Studio 2008 是否支持配置(调试/发布版本)特定参考?

    我有一个本机 C 项目 其中包含一个 C CLI 文件 唯一使用 CLI 编译的文件 我想添加对 C DLL 的引用 有单独的版本用于调试和发布 但是我似乎只能添加一个适用于所有配置的参考 引用搜索路径对话框包含一个警告 如果我尝试使用任何
  • Oracle 11g 重命名。保证是原子的?

    我在 plsql 脚本中有一些 5 重命名语句 drop table new rename old to new 旧 表包含非常有价值的信息 在我看来 如果重命名命令保证是原子的 那么我就解决了一个问题 它是原子的吗 如果没有 有没有办法进
  • 使用 Fancybox 版本 2 - 关闭第二个 fancybox 时重新打开第一个 fancybox 而不是简单地关闭

    使用由以下提供的 Fancybox 版本 2http fancyapps com fancybox support 我想从我的主页打开一个 fancybox 但在第一个 fancybox 中可以调用第二个 fancybox 但是当第二个精美
  • 使用 PostSharp 在 C# 中的构造函数上应用方面

    我正在 PostSharp 中研究各种概念 Updated 这是我的程序类 namespace myconstructor class Program static void Main string args createfolder st
  • 仅从 txt 文件中读取整数并将每个找到的值相加

    我正在尝试读取包含整数字符串的 txt 文件 我希望能够从该文件中获取整数并将每个值相加以创建总计 我已经成功地读取了该文件 并且能够识别整数和非整数 我该如何将整数相加呢 public void goalCount throws File
  • 智能感知和代码建议在 Visual Studio 2012 Ultimate RC 中不起作用

    I have just downloaded and installed Visual Studio 2012 Ultimate RC but I m having an issue with the intellisense it doe
  • 无法找到软件包 google-drive-ocamlfuse ,突​​然停止工作

    我最近一直在使用 colab 直到现在我使用 google drive ocamlfuse 将我的项目链接到我的驱动器 但它无法加载包 apt get update qq 2 gt 1 gt dev null apt get install
  • 在 SQL Server 中使用 childs 创建 JSON(Web 树的结构)

    请帮助我创建一个查询 或建议阅读哪些内容 我在 SQL Server 表中有一个树形结构 当所有后代节点都成为嵌套 JSON 对象时 我需要将表数据转换为具有子级的 Web 树的 JSON 格式 我有这个数据表 DROP TABLE IF
  • 是否存在针对特殊字符的 PowerShell 转义功能

    As with in the self answer I like to be able to remove control characters from text to get a single line string Does the
  • 获取鼠标指针下方的窗口句柄,同时忽略半透明窗口

    我创建了一个半透明表单 60 不透明度 黑色背景色 我的应用程序在整个屏幕上启动该表单并最大化 基本上 它在整个桌面上投射灰色 当用户将鼠标悬停在桌面上的窗口上时 我想获取该窗口的句柄 hWnd 对我来说最简单的方法是 暂时隐藏我的表单 或
  • Lambda 捕获实例变量

    在一次令人沮丧的调试会话后阅读 JLS 我发现 lambda 会捕获value有效最终局部变量 但如果您引用实例变量 它会捕获对该变量的引用 这对多线程代码有严重影响 例如 以下是从一个更大的程序中提取的 MCVE public class
  • wpf属性网格

    我的 WPF 应用程序需要一个 propertyGrid 经过大量搜索后我发现this当我将 propertyGrid 添加到表单并运行它时 我已经添加了程序集 exe 文件 但在表单中看不到它 xaml代码
  • GMail API超级管理员通过API访问其他用户帐户?

    我的机构目前自 2009 年初以来一直在运行 Google Apps for Education 我负责创建 删除 修改学生电子邮件帐户等 我已将所有现有的 C 应用程序从 GData 转换为新的 Admin SDK 生活很美好 上周 其中
  • EF 代码优先 - 配置一对零或一关系,无需共享 PK/FK

    我正在尝试在两个实体之间建立一对零或一的关系 并且我希望依赖实体仍包含其自己的 Indentity 列 而不是共享密钥 我想尽可能遵循约定 而不是显式声明任何不需要显式声明的内容 因此 不不必要数据注释或 Fluent api 子句 实体
  • .net JSON 日期格式

    作为 net 服务的响应 我得到以下日期格式 日期 1233323754523 0100 1233323754523 是时间戳格式的日期 但我不知道 0100 是什么意思以及如何从java代码生成它 Thanks 我假设时间戳采用 UTC
  • React Native无法连接到Android中的SSE

    我正在使用该包 https www npmjs com package react native sse 即使我从文档中复制粘贴代码 我也无法设法从 android 中的服务器接收事件 import EventSource from rea
  • 在谷歌地图中设置城市周围的边界

    我正在寻找一种使用 JavaScript 在 Google 地图 API V3 中设置特定城市 城镇周围边界的方法 API 中是否支持这种类型的事情 基本上 我不希望我的用户能够比城市更远地平移地图 包括乡村地区而不仅仅是城市范围 那么您想
  • 用 Java 下载文件。多线程,这有效吗?

    首先 每个人都需要知道我对 Java 编码还比较陌生 更准确地说 我对面向对象编程完全陌生 对于这个问题 我正在尝试创建一个下载类来更新进度条以显示其进度 可能还有我决定将来更新的其他内容 目前的问题是 在我看来 这不应该起作用 我可以在