2013.08.03
上课内容:文件操作与异常机制
这节课我们要讲的是文件操作与异常机制。
我们用过电脑的都知道,我们平时所有的应用程序、文本文档都是文件或者是由一堆文件在一起组成的。
如果用面向对象的思想,我们可以认为文件具有下面几个属性:文件路径,文件名,后缀名等。
而文件有下面几个方法:添加,删除,修改内容,修改后缀名,移动路径等。
这里我们说文件全名,是指带后缀名的文件名。
相对路径是不带盘符的,根目录就在我们的Java Project下,而绝对路径是带盘符的。
文件所属的包在java.io里,我们今天要用的是File类,通过API,我们看出File类有很多的方法,我们这里介绍几种最常用的。
首先是构造函数:
File(File parent, String child) 这里输入的是父目录和子字符串。
File(String pathname) 这里输入的是指定路径。
File(String parent, String child) 这里输入的是父路径和子路径
构造函数主要就是这三个,下面介绍一些方法:
首先是创建文件的方法:createNewFile() ,返回boolean值,能够创建有两个前提,一个是指定的目录必须存在,第二个是该文件夹下没有与该文件文件全名相同的文件。
然后我们介绍删除文件的方法:delete(),同样返回的也是boolean值。
判断文件是否存在的方法:exists(),同样也是返回boolean值。
得到文件绝对路径的方法:getAbsolutePath(),返回String类型的,为文件的绝对路径。
//我在文件处理中不小心用了getPath(),结果得到的是相对路径。
还有就是判断该File类对象是否是文件:isFile(),返回的boolean值。
判断该File类对象是否是目录:isDirectory(),返回的boolean值。
当我们要获得目录下所有文件和目录的文件:listFiles(),返回的抽象名路径数组。
当我们要获得磁盘的目录时:listRoots(),返回的是磁盘目录的路径数组。
当我们要创建一个目录时:mkdir(),但前提是必须存在父目录。
当没有父目录时,我们可以用:mkdirs(),这个可以创建很多目录。
文件类中大概就是这些比较常用,要调用其他方法的可以去查API。
下面我们介绍一下文件异常机制。
比如说我们要在一个目录下创建一个文件,但是该目录下有与该文件相同的文件名,这时就会抛出异常。
异常用Exception表示,错误用Error表示。一般我们把程序在编译和运行中的错误统称为异常,异常我们可以自己处理,但是错误一般是不能处理的,如文件溢出。
异常类主要有三种:
try{} catch(){}:当我们发现异常时,可以通过try和catch
throw:throw new Exception可以自定义异常
throws:可以向上抛出异常,但是上面必须用异常处理或者接着向上抛出异常,如果主函数也向上抛出异常,就由系统来处理。
今天我们要做的练习是要统计你磁盘中所有文件总数或者选择只统计某一种类型的文件或者根据文件名进行统计(多线程)。
我们先来看看效果图吧:
首先我们建立一个窗体:
public class FileFrame extends JFrame {
public static void main(String[] args) {
FileFrame ff = new FileFrame();
ff.initUI();
}
private void initUI() {
this.setSize(new Dimension(650, 600));// 设置窗体大小
this.setLocationRelativeTo(null);// 设置窗体局中
this.setDefaultCloseOperation(3);// 设置关闭按钮
this.setResizable(false);// 设置不可调节大小
this.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 20));// 设置流式布局
this.getContentPane().setBackground(Color.white);// 设置背景为白色
// 建立三个标签
JLabel jla1 = new JLabel("路径:");
JLabel jla2 = new JLabel("文件名");
JLabel jla3 = new JLabel("扩展名");
JComboBox<String> jb = new JComboBox<String>();// 目录下拉框
jb.addItem("全部");
jb.addItem("C:/");
jb.addItem("D:/");
jb.addItem("E:/");
jb.addItem("F:/");
jb.addItem("G:/");
jb.setPreferredSize(new Dimension(100, 24));// 设置大小
JTextField jtf = new JTextField();// 设置要输入文件名的文本框
jtf.setPreferredSize(new Dimension(100, 24));// 设置文本框大小
JComboBox<String> jcb = new JComboBox<String>();// 后缀名下拉框
jcb.addItem(".*");
jcb.addItem(".java");
jcb.addItem(".txt");
jcb.addItem(".exe");
jcb.addItem(".jpg");
jcb.setPreferredSize(new Dimension(100, 24));// 設置下拉框大小
JTextArea jta = new JTextArea(24, 41);// 新建一个多行输入文本框
jta.setEditable(false);// 设置不可编辑
jta.setOpaque(false);// 设置透明
jta.append("请点击开始确定按钮开始查找……");// 初始化字
JScrollPane jcp = new JScrollPane(jta);// 设置有拉动条的面板,将多行输入文本添加进去
jcp.setBorder(null);// 设置边界为空
jcp.setOpaque(false);// 设置透明
jcp.getViewport().setOpaque(false);// 设置透明
JButton jbu = new JButton("开始查找");// 建立开始查找按钮
jbu.setPreferredSize(new Dimension(100, 24));// 设置按钮大小
FileListener fl = new FileListener(jb, jtf, jcb, jta);// 建立监听器
jbu.addActionListener(fl);// 给按钮添加监听器
jla1.setFont(new Font("微软雅黑", Font.BOLD, 15));// 设置字体大小
this.add(jla1);// 路径文本框
jb.setFont(new Font("微软雅黑", Font.BOLD, 15));// 设置字体大小
this.add(jb);// 路程的复选框
jla2.setFont(new Font("微软雅黑", Font.BOLD, 15));// 设置字体大小
this.add(jla2);// 文件名文本框
jtf.setFont(new Font("微软雅黑", Font.BOLD, 15));// 设置字体大小
this.add(jtf);// 加入文件名输入框
jla3.setFont(new Font("微软雅黑", Font.BOLD, 15));// 设置字体大小
this.add(jla3);// 拓展名文本框
jcb.setFont(new Font("微软雅黑", Font.BOLD, 15));// 设置字体大小
this.add(jcb);// 文件格式复选框
jbu.setFont(new Font("微软雅黑", Font.BOLD, 15));// 设置字体大小
this.add(jbu);// 开始查找
jta.setFont(new Font("微软雅黑", Font.BOLD, 15));// 设置字体大小
this.add(jcp);// 加入路径
this.setVisible(true);// 设置窗体可见
}
}
然后我们建立一个按钮监听器,传入所需要的数据:
public class FileListener implements ActionListener {
private JComboBox<String> jb;
private JTextField jtf;
private JComboBox<String> jcb;
private JTextArea jta;
/**
* 构造函数
*
* @param jb
* @param jtf
* @param jcb
* @param jta
*/
public FileListener(JComboBox<String> jb, JTextField jtf,
JComboBox<String> jcb, JTextArea jta) {
this.jb = jb;
this.jtf = jtf;
this.jcb = jcb;
this.jta = jta;
}
public void actionPerformed(ActionEvent e) {
String path = jb.getSelectedItem().toString();// 得到路径
if (path.equals("全部"))// 全盘遍历
{
String[] str = { "C:/", "D:/", "E:/", "F:/", "G:/" };
// 循环开线程
for (int i = 0; i < str.length; i++) {
new FileThread(str[i], jtf, jcb, jta).start();
}
} else {
new FileThread(path, jtf, jcb, jta).start();// 根据传入的路径开线程
}
}
}
下面我们就可以建立线程开始写文件了!
public class FileThread extends Thread {
private String path;
private JTextField jtf;
private JComboBox<String> jcb;
private JTextArea jta;
/**
* 构造方法
*
* @param path
* @param jtf
* @param jcb
* @param jta
*/
public FileThread(String path, JTextField jtf, JComboBox<String> jcb,
JTextArea jta) {
this.path = path;
this.jtf = jtf;
this.jcb = jcb;
this.jta = jta;
}
/**
* 重写run方法
*/
public void run() {
jta.setText(null);// 设置多行文本内容为空
String filename = jtf.getText();// 得到文件名
String suffix = jcb.getSelectedItem().toString();// 得到后缀名
// 如果只有文件名而没有拓展名
if (!filename.equals("") && suffix.equals(".*")) // 如果只有文件名
{
rawbol = true;
} else {
rawbol = false;
}
// 得到文件名
if (suffix.equals(".*")) {
name = filename;
} else // 得到文件名加拓展名
{
name = filename + suffix;
}
int count = filecount(path);// 得到查找到的个数
jta.append("\n" + path.toCharArray()[0] + "盘内共有" + name + "文件" + count
+ "个");// 输出查找结果
}
/**
* 查找的文件方法
*
* @param path路径
* @return 找到文件的个数
*/
public int filecount(String path) {
int count = 0;// 新建记录文件个数
File file = new File(path);// 用得到的路径创建文件对象
if (file.isFile()) // 如果是文件
{
count++;// 加一
} else if (file.isDirectory()) // 如果不是文件
{
File[] listfile = file.listFiles();// 建立一个文件数组
if (listfile != null) // 如果不为空
{
for (int i = 0; i < listfile.length; i++) {
if (listfile[i].isFile()) // 如果是文件
{
if (rawbol) // 如果只有文件名
{
String pathtemp = listfile[i].getPath();// 得到路径
int m = pathtemp.lastIndexOf('\\');// 得到最后一个斜线
int n = pathtemp.lastIndexOf('.');// 得到点
if (m < n) // 如果点在斜线后面
{
String nametemp = pathtemp.substring(m + 1, n);// 得到文件名
if (nametemp.equals(name)) // 如果要查找的跟文件名相同
{
jta.append("\n"
+ listfile[i].getAbsolutePath());// 在文本框中输出结果
count++;// 文件数量加一
}
}
} else if (listfile[i].getName().endsWith(name)) // 如果以文件结尾
{
jta.append("\n" + listfile[i].getAbsolutePath());// 在文本框中输出结果
count++;// 文件数量加一
}
} else if (listfile[i].isDirectory()) // 如果是文件夹
{
count += filecount(listfile[i].getAbsolutePath());// 用递归找子目录下的路径
}
}
}
}
return count;
}
String name;// 文件名加扩展名,文件名可以为空
String fileraw;// 文件名,不包含扩展名
boolean rawbol;// 记录是否是文件名查找
}