这次试验比较变态,需要写很多可视化,任务量很大。
进度条的写法
实际上,除了实现DataInput和 DataOutput接口之外(DataInputStream和DataOutputStream也实现了这两个接口),
它和这两个类系毫不相干,甚至不使用InputStream和OutputStream类中已经存在的任何功能;
它是一个完全独立的类,所有方法(绝大多数都只属于它自己)都是从零开始写的。
这可能是因为RandomAccessFile能在文件里面前后移动,所以它的行为与其它的I/O类有些根本性的不同。总而言之,它是一个直接继承Object的,独立的类。
基本上,RandomAccessFile的工作方式是,把DataInputStream和DataOutputStream结合起来,
再加上它自己的一些方法,
比如定位用的getFilePointer( ),
在文件里移动用的seek( ),
以及判断文件大小的length( )、
skipBytes()跳过多少字节数。
此外,它的构造函数还要一个表示以只读方式("r"),
还是以读写方式("rw")打开文件的参数 (和C的fopen( )一模一样)。
它不支持只写文件。
只有RandomAccessFile才有seek搜寻方法,
而这个方法也只适用于文件。
BufferedInputStream有一个mark( )方法,
你可以用它来设定标记(把结果保存在一个内部变量里),
然后再调用reset( )返回这个位置,但是它的功能太弱了,而且也不怎么实用。
首先是布局的编写。
推荐采用一个,叫做GridBagLayout的布局。
setLayout(new GridBagLayout()); //会自动判断行列,不用填写。
private GridBagConstraints cons = new GridBagConstraints(); //add时候的约束条件
cons.weightx = 1; //权重 比较复杂,设置之后会使插件自动扩展填充,都设成一样的就好
cons.weighty = 1;
cons.gridx = x; //左上角的行号列号,从0开始
cons.gridy = y;
cons.gridwidth = z; //占几行几列
cons.gridheight = k;
add(JLable7,cons);
关键变量,如上。
核心技术上有详细介绍。
插件的定义
JLabel JLable7 = new JLabel("File Name:");
JLabel JLable8 = new JLabel("File to be merged");
JLabel JLable9 = new JLabel("Number of files:");
JLabel JLable10 = new JLabel("Target file:");
JButton mergeSource = new JButton("...");
JButton removeButton = new JButton("Remove");
JButton clearButton = new JButton("Clear");
JButton StartMerge = new JButton("Start merging");
JTextField FileNameMerge = new JTextField(20); //在初始化中设定长度,如果不设定的话,会以其中的字符串长度来确定其长度
JTextField fileNumber = new JTextField(5);
JTextField fileTargetMerge = new JTextField(30);
JProgressBar barMerge = new JProgressBar();
JTextArea fileList = new JTextArea(20,40);
private class FileMergePanel extends JPanel implements ActionListener{
@Override
public void actionPerformed(ActionEvent e){
JButton srcButton = (JButton)e.getSource(); //这个方法比较省力,但注意此处比较的是地址,变量方面要写好,最好写成static的
}
else if(srcButton==removeButton){
}
else if(srcButton==clearButton){
}
else if(srcButton==StartMerge){
}
}
}
选项卡的编写
public MyFileCut() {
super("Super File Cutter");
tabs = new JTabbedPane(); //java提供tabs的类直接add进去就行
add(BorderLayout.CENTER, tabs); // BorderLayout是默认管理器,所以可以直接用
init();
installTabs();
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(500, 600);
}
private Component addTab(String title, Component component) {
return tabs.add(title, component);//把自己写的控件add到tabs里
}
private void installTabs() {
for (String s : panels.keySet()) //map提供的好的写法
addTab(s, panels.get(s));
}
private void init() {
panels = new LinkedHashMap<String, JPanel>();
panels.put("File Cut", new FileCutPanel());
panels.put("File Merge", new FileMergePanel());
}
private JTabbedPane tabs;
private Map<String, JPanel> panels;
进度条的写法
bar.setString("0%");
bar.setPreferredSize(new Dimension(300, 25));
bar.setStringPainted(true); //设定在进度条上显示字符的方法
bar.setMinimum(0);
bar.setMaximum(100);
bar.setValue(0);
切文件与合并文件
private class doCut extends Thread{
@Override
public void run(){
tagFile = fileTarget.getText();
try{
RandomAccessFile in = new RandomAccessFile(srcFile,"r");
for(int i=0;i<cutNum;i++){
File outFile = new File(tagFile+"part"+i);
RandomAccessFile out = new RandomAccessFile(outFile,"rw");
for(int j=0;j<perSize*1000;j++){
int t=in.read();
if (t==-1) break;
out.write(t);
}
out.close();
int progress=100/cutNum*(i+1);
bar.setValue(progress);
bar.setString(progress+"%");
}
bar.setValue(100); //更新进度条用的
bar.setString(100+"%");
in.close();
}catch(Exception e){
System.out.println("File Exception!");
}
}
}
private class doMerge extends Thread{
@Override
public void run(){
String tagName=fileTargetMerge.getText();
try{
File outFile = new File(tagName);
RandomAccessFile out = new RandomAccessFile(outFile,"rw");
for(int i=0;i<mergeFileList.size();i++){
File inFile = new File(mergeFileList.get(i).toString());
RandomAccessFile in = new RandomAccessFile(inFile,"r");
int c=0;
while ((c=in.read())!=-1){
out.write(c);
}
in.close();
int progress=100/mergeFileList.size()*(i+1);
barMerge.setValue(progress);
barMerge.setString(progress+"%");
}
out.close();
barMerge.setValue(100); //更新进度条用的
barMerge.setString(100+"%");
}catch(Exception e){
}
}
}
RandomAccessFile不属于InputStream和OutputStream类系的。实际上,除了实现DataInput和 DataOutput接口之外(DataInputStream和DataOutputStream也实现了这两个接口),
它和这两个类系毫不相干,甚至不使用InputStream和OutputStream类中已经存在的任何功能;
它是一个完全独立的类,所有方法(绝大多数都只属于它自己)都是从零开始写的。
这可能是因为RandomAccessFile能在文件里面前后移动,所以它的行为与其它的I/O类有些根本性的不同。总而言之,它是一个直接继承Object的,独立的类。
基本上,RandomAccessFile的工作方式是,把DataInputStream和DataOutputStream结合起来,
再加上它自己的一些方法,
比如定位用的getFilePointer( ),
在文件里移动用的seek( ),
以及判断文件大小的length( )、
skipBytes()跳过多少字节数。
此外,它的构造函数还要一个表示以只读方式("r"),
还是以读写方式("rw")打开文件的参数 (和C的fopen( )一模一样)。
它不支持只写文件。
只有RandomAccessFile才有seek搜寻方法,
而这个方法也只适用于文件。
BufferedInputStream有一个mark( )方法,
你可以用它来设定标记(把结果保存在一个内部变量里),
然后再调用reset( )返回这个位置,但是它的功能太弱了,而且也不怎么实用。
最后贴上源码,文本框的响应没有加,逻辑也不算很健全,不过可以应付检查了。
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.File;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JRadioButton;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class MyFileCut extends JFrame {
public static void main(String[] args) {
new MyFileCut();
}
public MyFileCut() {
super("Super File Cutter");
tabs = new JTabbedPane();
add(BorderLayout.CENTER, tabs); // BorderLayout是默认管理器,所以可以直接用
init();
installTabs();
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(500, 600);
}
private Component addTab(String title, Component component) {
return tabs.add(title, component);
}
private void installTabs() {
for (String s : panels.keySet())
addTab(s, panels.get(s));
}
private void init() {
panels = new LinkedHashMap<String, JPanel>();
panels.put("File Cut", new FileCutPanel());
panels.put("File Merge", new FileMergePanel());
}
private JTabbedPane tabs;
private Map<String, JPanel> panels;
//------------------------------------------------------------
JLabel JLable1 = new JLabel("File Name:");
JLabel JLable2 = new JLabel("File Size:");
JLabel JLable3 = new JLabel("Block Size:");
JLabel JLable4 = new JLabel("KB");
JLabel JLable5 = new JLabel("Number of block:");
JLabel JLable6 = new JLabel("Target file:");
JTextField fileName = new JTextField(20);
JTextField fileSize = new JTextField(20);
JTextField fileTarget = new JTextField(20);
JTextField blockNumber = new JTextField(10);
JTextField definedSize = new JTextField(5);
JButton browse_source = new JButton("...");
JButton browse_target = new JButton("...");
JButton startCut = new JButton("Start cutting");
ButtonGroup group = new ButtonGroup();
JRadioButton box1 = new JRadioButton("1.44MB", true);
JRadioButton box2 = new JRadioButton("1.2MB", false);
JRadioButton box3 = new JRadioButton("720KB", false);
JRadioButton box4 = new JRadioButton("360KB", false);
JRadioButton box5 = new JRadioButton("Self defined", false);
JProgressBar bar = new JProgressBar();
//----------------------------------------------------------------------
JLabel JLable7 = new JLabel("File Name:");
JLabel JLable8 = new JLabel("File to be merged");
JLabel JLable9 = new JLabel("Number of files:");
JLabel JLable10 = new JLabel("Target file:");
JButton mergeSource = new JButton("...");
JButton removeButton = new JButton("Remove");
JButton clearButton = new JButton("Clear");
JButton StartMerge = new JButton("Start merging");
JTextField FileNameMerge = new JTextField(20);
JTextField fileNumber = new JTextField(5);
JTextField fileTargetMerge = new JTextField(30);
JProgressBar barMerge = new JProgressBar();
JTextArea fileList = new JTextArea(20,40);
//-----------------------------------------------------------
private class FileMergePanel extends JPanel implements ActionListener{
@Override
public void actionPerformed(ActionEvent e){
JButton srcButton = (JButton)e.getSource();
if (srcButton==mergeSource){
JFileChooser fDialog = new JFileChooser();
fDialog.setDialogTitle("添加要合并的文件");
int returnVal = fDialog.showOpenDialog(null);
if(JFileChooser.APPROVE_OPTION == returnVal){
mergeFileList.add(fDialog.getSelectedFile().getPath());
flashTextArea();
FileNameMerge.setText(fDialog.getSelectedFile().getPath());
}
}
else if(srcButton==removeButton){
int removeId = Integer.parseInt(fileNumber.getText());
mergeFileList.remove(removeId-1);
flashTextArea();
}
else if(srcButton==clearButton){
mergeFileList.clear();
flashTextArea();
}
else if(srcButton==StartMerge){
doMerge run = new doMerge();
run.start();
}
}
private void flashTextArea(){
String AreaString="";
for(int i=0;i<mergeFileList.size();i++){
AreaString+=(i+1)+" "+mergeFileList.get(i)+"\n";
}
fileList.setText(AreaString);
}
private void init(){
mergeFileList = new ArrayList<String>();
mergeSource.addActionListener(this);
removeButton.addActionListener(this);
clearButton.addActionListener(this);
StartMerge.addActionListener(this);
}
public void setCons(int x, int y, int z, int k) {
cons.gridx = x;
cons.gridy = y;
cons.gridwidth = z;
cons.gridheight = k;
}
public FileMergePanel() {
init();
setLayout(new GridBagLayout());
cons.weightx = 1;
cons.weighty = 1;
setCons(0, 0, 1, 1);
add(JLable7,cons);
setCons(1, 0, 3, 1);
add(FileNameMerge,cons);
setCons(4, 0,1,1);
add(mergeSource,cons);
//=====================================row_1=================================
setCons(0, 1, 1, 1);
add(JLable8,cons);
//=======================================row_2============================
setCons(0,2,5,5);
add(fileList,cons);
//=======================================row_3============================
setCons(0,7,1,1);
add(JLable9,cons);
setCons(1,7,1,1);
add(fileNumber,cons);
//=======================================row_4============================
setCons(1,8,1,1);
add(removeButton,cons);
setCons(3,8,1,1);
add(clearButton,cons);
//=======================================row_5============================
setCons(0,9,1,1);
add(JLable10,cons);
setCons(1,9,4,1);
add(fileTargetMerge,cons);
//=======================================row_6============================
setCons(0,10,1,1);
add(StartMerge,cons);
setCons(1,10,4,1);
add(barMerge,cons);
barMerge.setString("0%");
barMerge.setPreferredSize(new Dimension(300, 25));
barMerge.setStringPainted(true);
barMerge.setMinimum(0);
barMerge.setMaximum(100);
barMerge.setValue(0);
//=======================================row_7============================
}
private class doMerge extends Thread{
@Override
public void run(){
String tagName=fileTargetMerge.getText();
try{
File outFile = new File(tagName);
RandomAccessFile out = new RandomAccessFile(outFile,"rw");
for(int i=0;i<mergeFileList.size();i++){
File inFile = new File(mergeFileList.get(i).toString());
RandomAccessFile in = new RandomAccessFile(inFile,"r");
int c=0;
while ((c=in.read())!=-1){
out.write(c);
}
in.close();
int progress=100/mergeFileList.size()*(i+1);
barMerge.setValue(progress);
barMerge.setString(progress+"%");
}
out.close();
barMerge.setValue(100);
barMerge.setString(100+"%");
}catch(Exception e){
}
}
}
private GridBagConstraints cons = new GridBagConstraints();
private List mergeFileList;
}
private class FileCutPanel extends JPanel implements ActionListener,ItemListener{
@Override
public void itemStateChanged(ItemEvent e){
JRadioButton srcButton =(JRadioButton) e.getSource();
if (srcButton==box1){
perSize=14400;
blockNumber.setText((fileSizeInt/perSize+1)+"");
cutNum=fileSizeInt/perSize+1;
}
else if(srcButton==box2) {
perSize=12000;
blockNumber.setText((fileSizeInt/perSize+1)+"");
cutNum=fileSizeInt/perSize+1;
}
else if(srcButton==box3) {
perSize=720;
blockNumber.setText((fileSizeInt/perSize+1)+"");
cutNum=fileSizeInt/perSize+1;
}
else if (srcButton==box4){
perSize=360;
blockNumber.setText((fileSizeInt/perSize+1)+"");
cutNum=fileSizeInt/perSize+1;
}
else if (srcButton==box5){
perSize=Integer.parseInt(definedSize.getText());
blockNumber.setText((fileSizeInt/perSize+1)+"");
cutNum=fileSizeInt/perSize+1;
}
}
@Override
public void actionPerformed(ActionEvent e){
JButton srcButton = (JButton)e.getSource();
if (srcButton==browse_source){
JFileChooser fDialog = new JFileChooser();
fDialog.setDialogTitle("添加要分割的文件");
int returnVal = fDialog.showOpenDialog(null);
if(JFileChooser.APPROVE_OPTION == returnVal){
srcFile = fDialog.getSelectedFile().getPath();
cutFile = new File(srcFile);
fileSizeInt = (int) cutFile.length()/1000;
fileSize.setText(fileSizeInt + "K");
fileName.setText(srcFile);
blockNumber.setText((fileSizeInt/perSize+1)+"");
}
}
else if(srcButton==browse_source){
}
else if(srcButton==startCut){
doCut r =new doCut();
r.start();
}
}
private void setCons(int x, int y, int z, int k) {
cons.gridx = x;
cons.gridy = y;
cons.gridwidth = z;
cons.gridheight = k;
}
private void init(){
browse_source.addActionListener(this);
browse_target.addActionListener(this);
startCut.addActionListener(this);
box1.addItemListener(this);
box2.addItemListener(this);
box3.addItemListener(this);
box4.addItemListener(this);
box5.addItemListener(this);
}
public FileCutPanel() {
init();
setLayout(new GridBagLayout());
cons.weightx = 1;
cons.weighty = 1;
setCons(0, 0, 1, 1);
add(JLable1, cons);
setCons(1, 0, 3, 1);
add(fileName, cons);
setCons(4, 0, 1, 1);
add(browse_source, cons);
// =============================row_1==============================================
setCons(0, 1, 1, 1);
add(JLable2, cons);
setCons(1, 1, 3, 1);
add(fileSize, cons);
setCons(4, 1, 1, 1);
add(browse_target, cons);
// ================================row_2===============================================
setCons(0, 2, 1, 1);
add(JLable3, cons);
group.add(box1);
group.add(box2);
setCons(1, 2, 1, 1);
add(box1, cons);
setCons(3, 2, 1, 1);
add(box2, cons);
// =================================row_3===================================
group.add(box3);
group.add(box4);
setCons(1, 3, 1, 1);
add(box3, cons);
setCons(3, 3, 1, 1);
add(box4, cons);
// ===================================row_4========================================
group.add(box5);
setCons(1, 4, 1, 1);
add(box5, cons);
setCons(3, 4, 1, 1);
add(definedSize, cons);
setCons(4, 4, 1, 1);
add(JLable4, cons);
// ==================================row_5=========================
setCons(0, 5, 1, 1);
add(JLable5, cons);
setCons(1, 5, 2, 1);
add(blockNumber, cons);
// ==================================row_6=========================
setCons(0, 6, 1, 1);
add(JLable6, cons);
setCons(1, 6, 3, 1);
add(fileTarget, cons);
setCons(4, 6, 1, 1);
add(browse_target, cons);
// =================================row_7=================================
setCons(0, 7, 1, 1);
add(startCut, cons);
setCons(1, 7, 3, 1);
add(bar, cons);
bar.setString("0%");
bar.setPreferredSize(new Dimension(300, 25));
bar.setStringPainted(true);
bar.setMinimum(0);
bar.setMaximum(100);
bar.setValue(0);
// =================================row_8=================================
}
private class doCut extends Thread{
@Override
public void run(){
tagFile = fileTarget.getText();
try{
RandomAccessFile in = new RandomAccessFile(srcFile,"r");
for(int i=0;i<cutNum;i++){
File outFile = new File(tagFile+"part"+i);
RandomAccessFile out = new RandomAccessFile(outFile,"rw");
for(int j=0;j<perSize*1000;j++){
int t=in.read();
if (t==-1) break;
out.write(t);
}
out.close();
int progress=100/cutNum*(i+1);
bar.setValue(progress);
bar.setString(progress+"%");
}
bar.setValue(100);
bar.setString(100+"%");
in.close();
}catch(Exception e){
System.out.println("File Exception!");
}
}
}
private GridBagConstraints cons = new GridBagConstraints();
private String srcFile;
private String tagFile;
private File cutFile;
private int perSize=14400;
private int fileSizeInt;
private int cutNum;
}
}