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 ( "余额不足 无法取款" ) ;
}
}
}
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 [ ] 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) {
File file = new File ( "E:\\Test" ) ;
setName ( file) ;
}
private static void setName ( File file) {
File [ ] files = file. listFiles ( ) ;
for ( File f : files) {
if ( f. isFile ( ) && f. getName ( ) . endsWith ( ".jpg" ) ) {
String s = f. getName ( ) . replace ( ".jpg" , ".png" ) ;
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) ;
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 ( ) ;
}
}
}
}