Exception异常:分为运行时异常和编译时异常(非运行时异常,受检异常).
运行时异常:如果一个方法内部抛出了一个运行时异常,那么方法上可以声明也可以不声明,调用者可以处理也可以不处理.
编译时异常(非运行时异常,受检异常):如果一个方法内部抛出了一个编译时异常,那么方法上就必须要声明,而且调用者也必须要处理.
RuntimeException和它的子类都是运行时异常.
运行时异常都是可以通过程序员良好的编程习惯而避免的,所以java编译器没有严格要求运行时异常.
2.finally块:
使用前提:必须存在try块才能使用.
finally块在任何时候都会运行到,除非jvm退出.
finally非常适合做资源释放的工作,这样可以保证资源文件在任何情况下都会执行而被释放.
3.try块的三种组合方式:
1)适合有异常要处理但没有资源要释放
try{
可能发生异常的代码
}catch(捕获的异常类型 变量名){
处理异常代码
}
2)适合既有异常要处理,又有资源要释放
try{
可能发生异常的代码
}catch(捕获的异常类型 变量名){
处理异常代码
}finally{
释放资源的代码
}
3)适用于内部抛出的是运行时异常并且有资源要被释放
try{
可能发生异常的代码
}finally{
释放资源的代码
}
4.File文件类:
可以描述一个文件或者是文件夹
File类常用的方法:
创建:
createNewFile() 在指定位置创建一个空文件,成功就返回true,如果已存在就不创建返回false.
删除:
delete() 删除文件或者空文件夹,如果是文件夹且不为空,则不能删除,删除成功返回true,失败返回false.
判断:
exists() 判断文件或文件夹是否存在
isFile() 判断是否是一个文件
isDirectory() 判断是否是一个文件夹
isHidden() 是否是一个隐藏的文件或者是隐藏的目录
isAbsolute() 测试路径名是否是绝对路径名
获取:
getName() 获取文件夹的名称,不包含上级路径
length() 获取文件的字节数,如果文件不存在则返回0L,如果是文件夹也返回0L
getParent() 返回此路径名父目录的路径名字符串,如果此路径名没有指定父目录,则返回null
与文件夹相关方法:
listFiles() 返回目录下的文件或者是目录对象(File类实例),包含隐藏文件,对于文件这样操作会返回null
通过File对象我们可以读取文件或者文件夹的属性数据,如果我们需要读取文件的内容数据,则需要用到IO流技术
下面是实现通过路径搜索文件和文件夹功能的小项目:
package FileSearch;
import java.awt.BorderLayout;
import java.awt.ScrollPane;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
/**
*初始化窗体的工具类
*@author lvjiakai
*/
publicclassFrameextendsJFrame{
private JFrameframe =new JFrame("文件搜索");
private JPanelpanel =new JPanel();
private JTextFieldfield =new JTextField("请输入目录名...",25);
private JTextAreaarea =new JTextArea(1000,1000);
private JButtonbutton =new JButton("搜索");
private ScrollPanebar =new ScrollPane();
private Stringpath;
publicvoid init(){
//先把滚动条加到中间的area区域中
bar.add(area);
//之后把组件添加到panel面板上
panel.add(field);
panel.add(button);
//给输入框添加鼠标监听,点击时将输入框内容清空
field.addMouseListener(new MouseAdapter(){
publicvoid mouseClicked(MouseEvente){
field = (JTextField)e.getSource();
if("请输入目录名...".equals(field.getText())){
field.setText("");
}
}
});
//给按钮添加事件监听器
button.addActionListener(new ActionListener(){
publicvoidactionPerformed(ActionEvente){
//获取输入框输入的绝对路径
path =field.getText();
searchFile(path);
}
});
//在窗体北边添加panel面板
frame.add(panel,BorderLayout.NORTH);
//窗体剩余的部分添加area区域
frame.add(bar);
//初始化窗体
InitFrame.initFrame(frame,400,400);
}
publicvoid searchFile(Stringpath1){
//通过输入的绝对路径构建一个File对象
Filedir =new File(path1);
//找到目录下的所有子文件
File[]files =dir.listFiles();
for(Filefile:files){
if(file.isFile()){
area.setText(area.getText()+file.getName()+"\r\n");
}else{
if(file!=null){
area.setText(area.getText()+file.getName()+"\r\n");
searchFile(file.getAbsolutePath());
}
}
}
}
publicstaticvoid main(String[]args){
new Frame().init();
}
}
package FileSearch;
import java.awt.Dimension;
import java.awt.Toolkit;
import javax.swing.JFrame;
/**
*初始化窗体的工具类
*@author lvjiakai
*/
publicclassInitFrame{
publicstaticvoidinitFrame(JFrameframe,intwidth,intheight){
Toolkittoolkit = Toolkit.getDefaultToolkit(); //获取一个与系统相关工具类对象
//获取屏幕的分辨率
Dimensiond =toolkit.getScreenSize();
intx = (int)d.getWidth();
inty = (int)d.getHeight();
frame.setBounds((x-width)/2,(y-height)/2,width,height);
//设置窗体不能拉动变大变小
frame.setResizable(false);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
5.IO流:
IO流解决设备与设备之间数据传输的问题. 内存->硬盘 硬盘->内存
IO流按照数据流向分类:
输入流
输出流
IO流按照处理的单位划分:
字节流:字节流读取的是文件中的二进制数据,读取到二进制数据后不会经过任何的处理.
字符流:字符流读取的数据是以字符为单位的,也是读取文件中的二进制数据,不过会把这些二进制数据转换成我们能识别的字符.字符流 = 字节流+解码
输入字节流:InputStream:所有输入字节流的基类,是一个抽象类,不能直接创建对象.
FileInputStream:读取文件数据的输入字节流
输出字节流:OutputStream:所有输出字节流的基类,也是一个抽象类,不能直接创建对象.
FileOutputStream:向文件输出数据的输出字节流
使用FileOutputStream要注意的细节:
1)如果目标文件不存在,则会自动创建一个文件.
2)如果目标文件已存在,则会先清空数据,再重新写入.
3)如果目标文件已存在,则需要使用new FileOutputStream(file,true)的构造方法才能实现追加数据.
4)使用FileOutputStream的write方法写数据时,虽然接收的是一个int类型的数据,但是int类型的4个字节的数据只写出了1个字节,只是把低8位的二进制数据写出,剩余24位则全部舍弃.
字节流可读取txt、word文档、音乐、影视、图片等多种以二进制形式存储的文件.
目录分隔符:在Windows机器上的目录分隔符是\,在Linux机器上的目录分隔符是/
注意:在Windows下/与\都可以作为目录分隔符.而且,如果写/时只需写一个.
下面就是文件输入流读取写入文件的基本思想:
package org.lxh.demo;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
//IO异常的处理.
publicclass lvjiakai{
publicstatic void main(String[]args){
copyImage();
}
//需求:编写拷贝文件的异常
publicstaticvoid copyImage(){
FileInputStreamfileInputStream =null;
FileOutputStreamfileOutputStream =null;
try{
//找到目标文件
FileinFile =new File("F:\\a.docx");
FileoutFile =new File("E:\\a.docx");
//建立输入输出通道
fileInputStream = new FileInputStream(inFile);
fileOutputStream = new FileOutputStream(outFile);
//建立缓冲数组,边读边写
byte[]buf =newbyte[1024]; //相当于超市的购物车
intlength = 0;
while((length=fileInputStream.read(buf))!=-1){
fileOutputStream.write(buf,0,length); //只写buf会造成数组空间浪费,有多少字节就应该创建多大的数组
}
}catch(IOExceptione){
System.out.println("拷贝文件出错...");
thrownew RuntimeException(e);
}finally{
try{
if(fileOutputStream!=null) {//因为有可能读取的文件找不到引发空指针异常
fileOutputStream.close();
System.out.println("关闭输出流对象成功...");
}
}catch(IOExceptione){
System.out.println("关闭输出流资源失败...");
thrownew RuntimeException(e); //任何异常类型都可以这样包装,因为是Exception的构造方法,子类都可以用
}finally{
try{
if(fileInputStream!=null){
fileInputStream.close(); //无法保证这句话一定能执行,所以要分开来做
System.out.println("关闭输入流资源成功...");
}
}catch(IOExceptione){
System.out.println("关闭输入流资源失败...");
thrownew RuntimeException(e);
}
}
}
}
}
注意:1)读取完一个数组后,应该关闭资源,否则其它程序无法对该资源文件进行其它的操作.
2)如果字节数组长度不够长,那么下一次存储的数据会将第一次存储的数据覆盖.
3)关闭资源原则:先关后开,先开后关.
总结:
使用FileInputStream读取文件数据的步骤:
1)找到目标文件
2)建立数据的输入通道
3)读取文件中的数据
4)关闭资源
使用FileOutputStream输出文件数据的步骤:
1)找到目标文件
2)建立数据的输出通道
3)把数据转换成字节数组写出
4)关闭资源
输入字符流:Reader:所有输入字符流的基类,是一个抽象类,不能直接创建对象.
FileReader:读取文件的输入字符流.
输出字符流:Writer:所有输出字符流的基类,也是一个抽象类,不能直接创建对象.
FileWrter:写入文件的输入字符流.
使用FileWriter要注意的细节:
1)使用它写数据的时候,FileWriter内部是维护了一个字符数组的,写数据的时候会先将数据写入它维护的字符数组(在内存)中,如果真正要把数据写到硬盘上,则需要调用flush或者是close方法,或者数组被填满后会自动写入到硬盘中.
2)如果目标文件不存在,则会自动创建目标文件.
3)如果不想数据被覆盖,则需要使用new FileWriter(file,true)的构造方法来追加数据.
特别注意:使用字符流可以实现txt文本文档的拷贝,但是影像、图片等二进制文件进行拷贝会出现问题.
原因:用FileReader将文件内容以字节流读取进来后,会进行解码,通过GBK码表如果找不到对应的字符,则会返回一个未知字符,未知字符只占1个字节,因此有可能导致图片数据损失而无法打开.
总结:
使用FileReader读取文件数据的步骤:
1)找到目标文件
2)建立数据的输入通道
3)读取数据
4)关闭资源
使用FileWriter输出文件数据的步骤:
1)找到目标文件
2)建立数据输出通道
3)写出数据
4)关闭资源
缓冲输入字符流:BufferedReader,与FileReader并列,但是它的出现是为了提高和拓展FileReader类的功能,该类内部维护了一个字符数组,每次从内存中读取,会比从硬盘中读取快很多,因此效率提高.
注意:BufferedReader还有一个拓展方法readLine方法,返回的是字符串,它一次可以读一行文本,读到文件末尾返回null.
BufferedReader读取方法示例:
package org.lxh.demo;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Arrays;
publicclass lvjiakai{
publicstaticvoid main(String[]args)throws IOException{
readTest1();
}
publicstaticvoid readTest1()throws IOException {
//找到目标文件
Filefile =new File("F:\\a.txt");
//建立数据的输入通道
FileReaderfileReader =new FileReader(file);
//建立缓冲输入字符流(缓冲流都不具备读写文件的功能)
BufferedReaderbufferedReader =new BufferedReader(fileReader);
//读取数据
/*
int content = bufferedReader.read();
System.out.println((char)content);
*/
Stringline =null;
while((line=bufferedReader.readLine())!=null){//虽然readLine每次读取一行数据,但是返回的line是不包含\r\n的(到达整个流的末尾,返回null)
System.out.println(Arrays.toString("aaa".getBytes()));
}
//关闭资源
bufferedReader.close();
}
}
缓冲输出字符流:BufferedWriter,与FileWriter并列,但是它的出现是为了提高和拓展FileWriter类的功能,其实该类内部只是维护了一个8192长度的字符数组作为缓冲区.
BufferedWriter写入方法示例:
package org.lxh.demo;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
publicclass lvjiakai{
publicstaticvoid main(String[]args)throws IOException{
//建立数据的输出通道
FileWriterfileWriter =new FileWriter("F:\\a.txt",true);
//建立缓冲输出流对象
BufferedWriterbufferedWriter =new BufferedWriter(fileWriter);
//写出数据
bufferedWriter.write("大家好!");
bufferedWriter.newLine(); //newLine()换行,实际上就是向文件输出\r\n
bufferedWriter.write("你好!");
//关闭资源
bufferedWriter.close();
}
}
DataInputStream和DataOutputStream是专门用来读取和写入指定类型的数据的,可以将BufferedInputStream和BufferedOutputStream包装成数据流.
对象输入输出流:ObjectInputStream(无读取能力,需要传入InputStream)、ObjectOutputStream(无写入能力,需要传入OutputStream).
主要作用是读取对象和写对象的信息,对象信息一旦写到文件上,那么对象的信息就可以做到持久化了.
使用对象输入输出流的注意事项:
1)如果对象需要被写出到文件上,则必须实现Serializable接口,这个接口本身没有内部方法,是一个标识接口.
2)serialVersionUID是用于记录class文件的版本信息的,是通过一个类的类名、成员、包名、工程名算出的一个数字.
3)如果一个对象的某个数据不想被序列化到硬盘上,则可以使用transient修饰.
4)如果一个类维护了另外一个类的引用,则另外一个类也要实现Serializable接口.
对象输入输出流综合举例:
package org.lxh.demo;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
classAddressimplements Serializable{
Stringcountry;
Stringcity;
public Address(Stringcountry,Stringcity){
this.country = country;
this.city = city;
}
}
class UserimplementsSerializable{
privatestaticfinallongserialVersionUID= 1L;
StringuserName;
Stringpassword;
transientintage;
Addressaddress;
public User(StringuserName,Stringpassword){
this.userName = userName;
this.password = password;
}
public User(StringuserName,Stringpassword,intage,Addressaddress){
this.userName = userName;
this.password = password;
this.age = age;
this.address = address;
}
public String toString(){
return"用户名:"+this.userName+"密码:"+this.password+"年龄:"+this.age+"地址:"+this.address;
}
}
publicclasslvjiakai{
publicstaticvoid main(String[]args)throwsIOException,ClassNotFoundException{
writeObj();
readObj();
}
//把文件中的对象信息读取出来-------->对象的反序列化
publicstaticvoid readObj()throwsIOException,ClassNotFoundException{
//建立数据的输入通道
FileInputStreamfileInputStream =new FileInputStream("F:\\obj.txt");
//建立对象的输入流对象
ObjectInputStreamobjectInputStream =newObjectInputStream(fileInputStream);
//读取对象信息
Useruser = (User)objectInputStream.readObject(); //创建对象肯定要依赖对象所属的class文件
System.out.println("对象的信息:"+user);
}
//定义方法把对象的信息写到硬盘上------>对象的序列化
publicstaticvoid writeObj()throws IOException{
//把user对象的信息持久化存储
Addressaddress =new Address("中国","广州");
Useruser =new User("admin","123",15,address);
//建立数据输出流对象
FileOutputStreamfileOutputStream =new FileOutputStream("F:\\obj.txt");
//建立对象的输入流对象
ObjectOutputStreamobjectOutputStream=newObjectOutputStream(fileOutputStream);
//把对象写出
objectOutputStream.writeObject(user);
//关闭资源
objectOutputStream.close();
}
}
总结:
使用ObjectOutputStream输出对象的步骤:
1)找到目标文件
2)建立数据的输出流对象
3)建立对象的输出流对象将数据通过输出流对象传递进去
4)把对象写出
5)关闭资源
PS:本人初学,还有不少疑惑,希望博友们多多指点,共同进步!!!!