IO流(异常 File类)

IO流

IO流概述
	IO流是用来处理设备之间的数据传输
	上传文件 下载文件 复制文件
IO流前奏
	需要先学习 异常与File类
	File表示的是IO流将来要操作的文件
	上传下载文件时 可能会出现问题 需要通过异常解决

异常

异常概述
	异常就是Java程序在运行过程中出现的错误
异常的分类
	Error
        Java虚拟机无法解决的问题
    Exception
        编译时异常 非RuntimeException
        运行时异常 RuntimeException
异常体系图
	Serializable接口
		Throwable
			Error 
			Exception
				RuntimeException
				非RuntimeException
Throwable常见方法
public String getMessage()
返回该错误的详细信息
public String toString() 
返回这个异常的简短信息
public void printStackTrace()
获取异常类名和异常信息 以及异常出现在程序中的位置
printStackTrace(PrintStream s) 
打印该时间和指定的打印流的回溯
编译期与运行期的区别
所有的RuntimeException类及其子类的实例被称为运行期异常 其他的异常就是编译期异常
编译时异常:Java程序必须显示处理 否则程序就会发生错误 无法通过编译
运行时异常:无需显示处理 也可以和编译时异常一样处理
JVM处理异常
main函数接收到异常后 有两种处理方法
a.自己处理问题 程序继续运行
b.自己没有处理问题的能力 交给调用main的JVM来处理
	JVM处理异常:将异常名称 异常信息 异常出现的位置打印在控制台上 同时停止程序运行 
处理异常的方式
a. try...catch...finally
	被finally控制的语句体一定会执行(前提jvm没有停止)
	finally用来释放资源
	特殊情况:在执行到finally之前jvm退出了(System.exit(0))
	方式一:
        try	{
            可能出现问题的代码;
        }catch(异常名 变量名){
            针对问题的处理;
        }finally{
            释放资源;
        }
        //try中代码越少越好
        //catch中要做处理
        
    方式二:
        try {
            可能出现问题的代码;
        }catch(异常名1 变量名1){
            对异常的处理方式;
        }catch (异常名2 变量名2){
            对异常的处理方式;
        }....
        //若出现了子父关系 父必须在后面

    方式三:
        try {
        	可能出现问题的代码 ;
        }catch(异常名1 | 异常名2 | ....   变量名){
        	对异常的处理方案 ;
        }
        //简化了代码
        //弊端:对多个异常的处理方式是一致的
        //多个异常之间只能是平级的关系,不能出现父子类的继承关系
    
b. throws
	定义功能方法时 把问题抛出让调用者去处理
	在方法声明后使用 后面跟异常类名
	格式: 方法名() throws 异常类名
finally关键字例题
面试题1:final,finally和finalize的区别
	final:
		final是一个状态修饰符 
		可以修饰类 变量 成员方法
		修饰的类不能被子类继承
		修饰的变量其实是一个常量 不能再次赋值
		修饰的成员方法不能被子类重写
	finally:
		用在异常的处理方法中try...catch...finally
		用于释放资源
		始终会被执行(前提:JVM不能退出)
	finalize:
		是Object类中的方法
		用于垃圾回收
		
面试题2:如果catch里面有return语句,请问finally的代码还会执行吗?		   如果会 请问是在return前还是return后?
	答: finally代码还会执行 在return前执行

	public static void main(String[] args) {
        try {
            System.out.println(2/0);
            //return;
        } catch (Exception e) {
            e.printStackTrace();
            return;
        } finally {
            System.out.println("finally被执行");
        }

        /*
        java.lang.ArithmeticException: / by zero
        at org.异常.Test.main(Test.java:11)
        finally被执行
        */
    }
自定义异常
在开发中会遇到很多问题 
而JDK不可能对每一种问题都给出具体的异常类与之对应
为满足需求 我们就需要自定义异常

自定义异常概述
	将我们自定义的异常类纳入异常体系中
	继承 Exception
	继承 RuntimeException
throw和throws的区别
throw
    用在方法体内 跟的是异常对象名
    只能抛出一个异常对象名
    这个异常对象可以是编译期异常和运行期异常对象
    表示抛出异常 由方法体内的语句处理
    throw则是抛出了异常 执行throw则一定抛出了某种异常
throws
    用在方法声明后面 跟的是异常类名
    可以跟多个异常类名 用逗号隔开
    表示抛出异常 由该方法的调用者来处理
    throws表示出现异常的一种可能性 并不一定会发生这些异常
银行取钱(自定义异常)
public class Mytest {
    public static void main(String[] args) {
        //需求:从银行取钱,发现钱不够,给出提示
        
        //设置总金额
        int money = 100;
		//键盘录入信息
        Scanner scanner = new Scanner(System.in);
        System.out.println("余额=" + money + "元");
        System.out.println("请输入需要取出的金额");
        int getMoney = scanner.nextInt();
		//判断
        money -= getMoney;
        if (money >= 0) {
            System.out.println("取款成功 余额=" + money + "元");
        } else {
            throw new MoneyException("余额不足 无法取款");
        }

    }
}
//定义余额异常 继承RuntimeException类
public class MoneyException extends RuntimeException {
    public MoneyException(String message) {
        super(message);
    }
}
异常的注意事项及如何使用异常处理
注意事项
a:子类重写父类方法时 子类的方法必须抛出相同的异常 或父类异常的子类 或者子类不抛出异常 
b:如果父类抛出了多个异常 子类重写父类时 只能抛出相同的异常 或者是他的子集 子类不能抛出父类没有的异常 或者子类不抛出异常 
c:如果被重写的方法没有异常抛出 那么子类的方法绝对不可以抛出异常 如果子类方法内有异常发生 那么子类只能try 不能throws

使用异常处理
后续程序需要继续运行就try
后续程序不需要继续运行就throws

File类

File类概述
	文件和目录路径名的抽象表示形式
	File类可以表示文件也可以表示目录

构造方法
    File(String pathname)
    根据一个路径得到File对象    
    File(String parent, String child) 
    根据一个目录和一个子文件/目录得到File对象
    File(File parent, String child)
    根据一个父File对象和一个子文件/目录得到File对象
创建功能
	public boolean createNewFile()
	创建新文件 若文件存在就不再创建
	public boolean mkdir()
	创建目录(单层目录) 若目录存在就不再创建
	public boolean mkdirs()
	创建目录(多层目录/单层目录) 若目录存在就不再创建
删除功能
	public boolean delete()
	删除文件或目录(只能删除空目录)
重命名功能
	public boolean renameTo(File dest)
	把文件重命名为指定的文件路径
	如果路径名相同,就是改名
	如果路径名不同,就是改名并剪切
判断功能
	public boolean isDirectory()
    判断是否为目录
    public boolean isFile() 
    判断是否为文件
    public boolean exists() 
    判断是否存在
    public boolean canRead() 
    判断是否可读
    public boolean canWrite() 
    判断是否可写
    public boolean isHidden()
    判断是否隐藏
    public boolean isAbsolute()
    判断是否使用的是绝对路径
获取功能
	public String getAbsolutePath()
	获取绝对路径
	public String getParent()
	获取父目录的路径名
	如果此路径名没有指定父目录 则返回null
    public File getParentFile()
    获取父目录的路径文件夹
    如果此路径名没有指定父目录 则返回null 
	public long getTotalSpace()
    获取此抽象路径名指定的分区大小
    返回总容量 单位字节
	public long getFreeSpace()
    获取此抽象路径名指定的分区中未分配的字节数 
    返回剩余容量 单位字节
	public String getName()
    获取名称
	public long length()
    获取长度(字节数)
	public long lastModified()
    获取最后一次的修改时间 毫秒值
	public String[] list()
    获取指定目录下的文件或文件夹的名称数组
	public File[] listFiles()
    获取指定目录下的文件或者文件夹的file数组
文件名称过滤器
public String[] list(FilenameFilter filter)
获取指定目录下的文件或文件夹的名称数组
格式:
    String[] list = file.list(new FilenameFilter() {
        @Override
        public boolean accept(File dir, String name) {
            return dir.isFile() && name.endsWith(".jpg");
        }
    });
    
public File[] listFiles(FilenameFilter filter)
public File[] listFiles(Filter filter)
获取指定目录下的文件或者文件夹的file数组
格式:
    File[] files = file.listFiles(new FilenameFilter() {
        @Override
        public boolean accept(File dir, String name) {
        	return dir.isDirectory() && name.endsWith(".png");
        }
    });
    
	File[] files = file.listFiles(new FileFilter() {
        @Override
        public boolean accept(File pathname) {
        	return pathname.isFile() && pathname.getName().endsWith("jpg");
        }
    });
递归删除多级文件夹
public class DeleteDir2 {
    public static void main(String[] args) {
        //要删除的目录
        File file = new File("E:\\Demo");
        deleteDir(file);
    }

    private static void deleteDir(File file) {
        //获取file数组
        File[] files = file.listFiles();
        //遍历
        for (File f : files) {
            //如果是文件就直接删除
            //如果是空目录也直接删除
            if (f.isFile()){
                f.delete();
            }else {
                //如果是目录 进行递归操作
                //直到找到最底层的文件或空目录
                deleteDir(f);
                //删除该目录
                f.delete();
            }
        }
        //删除最外层的目录
        file.delete();
    }
}
递归修改多级文件夹中的文件名
public class SetName {
    public static void main(String[] args) {
        //判断多级文件夹下有没有.jpg结尾的文件,如果有把后缀名 .jpg 文件改为.png
        //要修改的目录
        File file = new File("E:\\Test");
        setName(file);
    }

    private static void setName(File file) {
        //获取文件数组
        File[] files = file.listFiles();
        //遍历
        for (File f : files) {
            //判断是否为文件且文件名结尾是否为.jpg
            if (f.isFile()&&f.getName().endsWith(".jpg")){
                //修改文件名的结尾处
                String s = f.getName().replace(".jpg", ".png");
                //通过renameTo方法修改文件名(路径与f的路径一致) 
                f.renameTo(new File(f.getParent(),s));
            }
            //如果是目录
            if (f.isDirectory()){
                //递归进行修改文件名
                setName(f);
            }
        }
    }
}
递归复制多级文件夹
public class copyDir {
    public static void main(String[] args) {
        //创建数据源目录 从哪里来的文件夹
        File source = new File("E:\\Test");
        File target = new File("E:\\Demo");
        copyDir(source, target);


    }

    private static void copyDir(File source, File target) {
        //创建数据目的目录 到哪里去的文件夹
        target = new File(target, source.getName());
        //在数据目的处创建与数据源目录相同名字的目录
        target.mkdirs();
        //获取数据源中所有文件 包含文件夹
        File[] sourceFiles = source.listFiles();
        for (File sourceFile : sourceFiles) {
            //如果是文件
            if (sourceFile.isFile()) {
                //获取该数据源文件的名字
                String sourceFileName = sourceFile.getName();
                //创建一个 父目录为数据目的目录 子目录为数据源文件 的文件
                File targetFile = new File(target, sourceFileName);
                //通过IO流复制文件
                copyFile(sourceFile, targetFile);
            }
            //如果是目录
            if (sourceFile.isDirectory()) {
                //进行递归操作
                //数据源则变成该目录
                copyDir(sourceFile, target);
            }

        }
    }

    private static void copyFile(File sourceFile, File targetFile) {
        FileInputStream in = null;
        FileOutputStream out = null;
        try {
            in = new FileInputStream(sourceFile);
            out = new FileOutputStream(targetFile);
            byte[] bytes = new byte[1024];
            int readLen = 0;
            while ((readLen = in.read(bytes)) != -1) {
                out.write(bytes, 0, readLen);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值