目录
GIF演示
代码
此示例涵盖的知识点:线程、IO流、File、Swing、Listener、JFrame、JFileDialog、JOptionPane、JProgressBar、Timer
GIF演示
代码
package psn.exer.progress;
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.util.UUID;
/**
* on 2023/3/4 21:20
*/
public class FileTrans {
public static void main(String[] args) {
new FileTrans().init();
}
public void init() {
JFrame jf = new JFrame();
JButton btn = new JButton("传输文件");
FileDialog fld = new FileDialog(jf, "请选择需要传输的文件", FileDialog.LOAD);
FileDialog fsd = new FileDialog(jf, "请选择文件保存的位置", FileDialog.SAVE);
fld.setBounds(400, 200, 400, 300);
fsd.setBounds(400, 200, 400, 300);
jf.add(btn, BorderLayout.NORTH);
btn.addActionListener(e -> {
//暂时禁用按钮,防止多次点击按钮并进行多次文件传输,造成界面上多个进度条频繁切换
btn.setEnabled(false);
//开始选择文件,并将其信息传递给进度条和文件传输线程
fld.setVisible(true);
if (fld.getFile() == null || fld.getFile() == "") {
JOptionPane.showConfirmDialog(jf, "请选择需要传输的文件!", "未选择文件", JOptionPane.CLOSED_OPTION);
btn.setEnabled(true);
return;
}
//选择文件保存位置,设置文件名
JOptionPane.showConfirmDialog(jf, "请选择文件保存的位置", "提示信息", JOptionPane.CLOSED_OPTION);
fsd.setVisible(true);
if (fsd.getFile() == null || fsd.getFile() == "") {
JOptionPane.showConfirmDialog(jf, "请输入文件名", "未输入文件名", JOptionPane.CLOSED_OPTION);
btn.setEnabled(true);
return;
}
//创建文件传输任务
FileTransTask task = new FileTransTask(
new File(fld.getDirectory(), fld.getFile()),
new File(fsd.getDirectory(), fsd.getFile() + fld.getFile().substring(fld.getFile().lastIndexOf("."))),
1024);
//创建进度条,设置其外观:完成部分颜色、边框、完成百分比及字体
JProgressBar pb = new JProgressBar(JProgressBar.HORIZONTAL, 0, task.getTotal());
pb.setForeground(new Color(73, 156, 84));
pb.setBorderPainted(true);
pb.setStringPainted(true);
pb.setFont(new Font("等线", Font.ITALIC, 18));
jf.add(pb, BorderLayout.SOUTH);
//使进度条呈现
jf.validate();
//将文件传输任务交由此线程执行
Thread ft = new Thread(task, "file-trans");
ft.start();
//创建定时监听线程timer,其任务是每隔1毫秒获取传输完成量,然后更新进度条的值
Timer timer = new Timer(1, e1 -> pb.setValue(task.getFinished()));
timer.start();
//给进度条注册改变监听器,文件上传任务结束后,立即结束timer线程,提示用户操作成功,进度条不可见并移除进度条,开启上传按钮
pb.addChangeListener(e2 -> {
if (task.getFinished() >= pb.getMaximum()) {
timer.stop();
JOptionPane.showConfirmDialog(jf, "文件传输完毕!", "操作成功", JOptionPane.CLOSED_OPTION);
pb.setVisible(false);
jf.remove(pb);
btn.setEnabled(true);
}
});
});
//窗口基本设置
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setTitle("实现真实文件的传输");
jf.setBounds(400, 200, 400, 300);
jf.setVisible(true);
}
}
class FileTransTask implements Runnable {
private int bufferSize;//缓冲区字节数
private int total;//文件总字节数
private volatile int finished;//传输完成字节数
private File originFile;//源文件
private File destFile;//目标文件(另存为的文件)
public int getFinished() {
return finished;
}
public int getTotal() {
return total;
}
/**
* @param originFile 源文件
* @param destFile 另存为的文件
* @param bufferSize 文件传输缓存区大小
*/
public FileTransTask(File originFile, File destFile, int bufferSize) {
this.bufferSize = bufferSize;
this.originFile = originFile;
this.destFile = destFile;
if (originFile != null) {
this.total = (int) originFile.length();
}
finished = 0;
}
@Override
public void run() {
try {
FileInputStream fis = new FileInputStream(this.originFile);
FileOutputStream fos = new FileOutputStream(this.destFile);
byte[] buf = new byte[this.bufferSize];
//开始边读边存文件
while (true) {
fis.read(buf);
if ((total - finished) <= bufferSize) {//一次就传输完毕或者分多次传输的最后一次
fos.write(buf, 0, total - finished);
finished = total;//结束传输的条件
break;
} else {
finished += bufferSize;
fos.write(buf);
}
Thread.sleep(100);//增加文件传输耗时
}
fos.close();
fis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}