异常、File文件、IO流基础分析

来源:互联网 发布:jquery数组去掉字符串 编辑:程序博客网 时间:2024/05/23 12:56
1.异常:

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:本人初学,还有不少疑惑,希望博友们多多指点,共同进步!!!!



0 0