在前面的博客中,我简单的写了下关于大型文件的切割代码。
现在我又改进了下用图形界面来写这个,不过说实在的JAVA的图形界面实在有点难看,不过我们的主要学习重点也不是在图形界面上,所以大家不要太在意界面的难看了。下面我们来说说程序
*需求分析:
实现对大文件的切割与合并。
按指定个数切(如把一个文件切成10份)或按指定大小切(如每份最大不超过10M),这两种方式都可以。
示例程序说明:
文件切割:把一个文件切割成多个碎片,每个碎片的大小不超过1M。自己可把功能进一步扩展:切割前的文件名、长度,切割后的碎片个数、文件名等信息可写到第一个碎片中或另外用properties把这些写到配置文件中。
文件合并:这里简单假设已知被合并目录的File对象和原文件的名字。其实这些完全可以做成活的,如把这些信息保存在碎片文件或配置文件,也可以同样用文件选择对话框来读取用户的选择。
项目的目的:
一个简单的图形界面,主要的功能是做文件的切割,以及文件合并切割后想在哪个文件中合并就在哪里合并,在代码中的命名什么的也是个人喜好了
重点内容
在本代码中,个人觉得可以学习的地方,在设置背景,以及文件切割和合并的代码上,在设置背景 setBak();中需要注意透明度以及在this.getContentPane().setLayout(null); // 流动布局设置为空
我所有的组件都是绝对布局来设定的,这个看个人喜好了,
具体需要注意的细节我在代码中也写了,有不好的地方请大家多指教了
package io2;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.SequenceInputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
/**
* 用图形界面来做一个文件切割的工具类
*/
public class FileSplitSwing extends JFrame implements ActionListener {
String dir = “./image/”;// 图片路径
private JPanel mainPanel;// 主面板
private JTextArea splitetxt;// 显示切割文件
private JButton megerBtn;// 合并文件
private JButton select;// 选择切割的文件
private JLabel srcLb;// 合并路径的标签
private JTextField selectTxt, srcTxt;
private File file = null;// 要切割的文件
private File dest = null;// 目的地文件
public String fileName;// 选择切割的文件名
public String megerFile;// 合并文件路径
public FileSplitSwing() {
// 版面初始化
this.setTitle("文件切割器");
this.setBounds(200, 100, 500, 650);
this.setResizable(false);
this.getContentPane().setLayout(null); // 流动布局设置为空
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
// 设置背景图片函数
setBak();
invita();// 初始化界面
this.setVisible(true);
}
private void invita() {
// 全部控件用绝对布局
// 选择按钮
select = new JButton("选择切割的文件");
select.setBounds(0, 0, 125, 30);
selectTxt = new JTextField();
selectTxt.setBounds(125, 0, 375, 30);
selectTxt.setEditable(false);
// 切割按钮
splitetxt = new JTextArea(" 显示切割后的文件:");
splitetxt.setLineWrap(true);// 设置自动换行
splitetxt.setBounds(50, 30, 375, 400);
// 合并按钮
srcLb = new JLabel("合并的文件路径");
srcLb.setBounds(0, 500, 120, 30);
srcTxt = new JTextField();
srcTxt.setBounds(120, 500, 375, 30);
megerBtn = new JButton("合并文件");
megerBtn.setBounds(125, 550, 125, 30);
// 将控件板加到界面
this.getContentPane().add(select);
this.getContentPane().add(selectTxt);
this.getContentPane().add(splitetxt);
this.getContentPane().add(srcLb);
this.getContentPane().add(srcTxt);
this.getContentPane().add(megerBtn);
// 添加事件监听
select.addActionListener(this);
megerBtn.addActionListener(this);
}
// 设置背景
private void setBak() {
((JPanel) (this.getContentPane())).setOpaque(false);// 设置透明度
ImageIcon bgimage = new ImageIcon(dir + "beijing2.jpg");
JLabel bglabel = new JLabel(bgimage);
bglabel.setBounds(0, 0, bgimage.getIconWidth(), bgimage.getIconHeight());
// this.add(bglabel);// 这样不行要分成来显示图片
this.getLayeredPane().add(bglabel, new Integer(Integer.MIN_VALUE));
}
// 主函数
public static void main(String[] args) {
FileSplitSwing fss = new FileSplitSwing();
}
// 事件监听
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource().equals(select)) {
// 选择按钮监听
JFileChooser jf = new JFileChooser();
int result = jf.showOpenDialog(null);
if (result == JFileChooser.APPROVE_OPTION) {// 选中文件
file = jf.getSelectedFile();// 用户选择的文件
fileName = file.getName();
selectTxt.setText(fileName);
dest = new File(file.getParent(), "spliFile");
// 切割函数
cutingFile(file, dest);// 切割方法
File[] path = dest.listFiles();
String str = "";
for (int i = 0; i < path.length; i++) {
str += path[i].getName() + "\r\n";
}
splitetxt.setText(str);// 用String输出
}
}
if (e.getSource() == megerBtn) {
if (srcTxt == null) {
JOptionPane.showConfirmDialog(this, "存储路径不能为空~!");
}
megerFile = srcTxt.getText();// 合并路径,可以自己合并到哪里就哪里
mergeDemo(dest, fileName, megerFile);// 合并文件
}
}
private void mergeDemo(File dest2, String fileName, String megerFile) {
try {
// 防护(用File对象去开道),防止文件不存在
if (!dest.exists()) {
throw new RuntimeException("文件不存在");
}
// 用一个文件数组将里面的文件都装起来
File parth[] = dest.listFiles();// 返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。
if (parth.length == 0) {
throw new RuntimeException("碎片不存在");
}
// y用序列流来合并
ArrayList<FileInputStream> list = new ArrayList<FileInputStream>();
// for (int i = 0; i < parth.length; i++) {
// list.add(new FileInputStream(parth[i]));//不能这样,这样合并出来的文件是顺序乱的
// }
for (int i = 0; i < parth.length; i++) {
list.add(new FileInputStream(new File(dest, (i + 1) + fileName
+ "part")));// 套接技术,文件加的顺序要和原文件一样
}
// 枚举对象接口
Enumeration<FileInputStream> en = Collections.enumeration(list);
SequenceInputStream sq = new SequenceInputStream(en);
// 写入到新文件中
FileOutputStream fou = new FileOutputStream(new File(megerFile,
fileName));
byte buf[] = new byte[1024];
sq.read(buf);
int len = 0;
while ((len = sq.read(buf)) > 0) {
fou.write(buf, 0, len);
}
fou.close();
sq.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
// 切割
private void cutingFile(File source, File dest2) {
try {
FileInputStream fis = new FileInputStream(source);
if (!dest.exists()) {// 文件操作IO流要判断文件是否存在。
dest.mkdir();
}
byte buf[] = new byte[1024 * 1024];// 1M
fis.read(buf);
int len = 0;
int cout = 1;
while ((len = fis.read(buf)) != -1) {
// 用OUT流来切割文件
FileOutputStream fout = new FileOutputStream(new File(dest,
(cout++) + source.getName() + "part"));// 自定义格式
fout.write(buf, 0, len);
fout.close();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}