黑马程序员--Java基础之IO流(1)

来源:互联网 发布:人工智能 人类 奴隶 编辑:程序博客网 时间:2024/06/07 12:22

黑马程序员--Java基础之IO流(1)

---------------- android培训、java培训、期待与您交流! --------------------

一、概述

1、IO流用来处理设备之间的数据传输。

流操作数据分为两种:字节流与字符流。字符流的对象中糅合了编码表。

流按流向又分为:输入流,输出流。一般都是成对出现。

2、IO流常用基类

(1)字节流的抽象基类:InputStream,OutputStream

(2)字符流的抽象基类:Reader,Writer

二、常用流

1、字符流FileWriter,对文件操作的字符流,写入流。

 FileWriter fw = newFileWriter("demo.txt");//创建一个FileWriter对象,该对象一被初始化就必须要明确被操作的文件。//而且该文件会被创建到指定目录下。如果该目录下已有同名文件,该同名文件将会被覆盖。//其实该步骤就是在明确数据要存放的目的地。 fw.write("afgsdhdf");//write方法,将字符串写入到流中。但是这样并没有将字符串真正的写进目的地,而是写进了流中去//所以要刷新一下才能将缓冲区中的字符串写入到目的地。 fw.flush();//刷新之后还可以再写再刷。 fw.close();//关闭流资源,但是关闭之前会刷新一次内部的缓冲区中的数据,将数据存入到目的地中,关闭之后不能再写。//close和flush的区别:flush刷新后,流可以继续使用,close刷新后,会将流关闭。

对已有文件的数据续写:FileWriter的另一个构造函数:FileWriter(StringfileName ,boolean append);

FileWriter fw = newFileWriter("demo.txt",true);fw.write("sidjfvsldo\r\nvskirfj");//传递一个true参数,代表不覆盖已有的文件,并在已有文件的末尾处进行数据续写。

2、字符流FileReader,对文件操作的字符流,读取流。

第一种读取方式:通过字符进行读取。

FileReader fr =new FileReader("demo.txt");//创建一个文件读取流对象,和指定名称的文件相关联。要保证该文件是已经存在的,如果不存在,会发生异常:FileNotFoundException。接下来调用read()方法一次读一个字符,读取完毕会返回-1,然后利用循环。int ch = 0;while((ch =fr.read()) != -1){System.out.println((char)ch);} 

方式二:通过字符数组进行读取。

原理:定义一个数组缓冲区,将文件中的内容先读取到这个缓冲数组中,然后读出来,接着读取下一轮,下一轮取出的数覆盖原来的数组中的内容。

FileReader fr = new FileReader("demo.txt");char[] buf = new char[1024];//定义一个字符数组,用于存储读到的字符,一般用1024,这样比较合理,文件内容多了不至于多次循环int num =0;while((num = fr.read(buf)) != -1){System.out.print(new String(buf,0,num));}//读几个,打印几个,并且转化成字符串。fr.close();

3、字符流的缓冲区:BufferedWriter,BufferedRead

缓冲区的出现提高了对数据的读写效率,在流的基础上对流的功能进行了增强。

4、通过缓冲区复制文本文档

package cn.itheima.io;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException; public class CopyPractice {   public static void main(String[] args)   {  //定义一个写一个读的缓冲区      BufferedWriter bfw = null;      BufferedReader bfr = null;      try      {        FileWriter fw = new FileWriter("BufferDemo.txt");          bfw = newBufferedWriter(fw);        FileReader fr = new FileReader("Test.txt");        bfr = new BufferedReader(fr);        String line = null;        while((line=bfr.readLine())!= null)//一行一行读        {           bfw.write(line);//每读完一行就写一行           bfw.newLine();//写完一行就换行           bfw.flush();//刷新一下        }      }      catch(IOException ie)      {        System.out.println(ie.getMessage());      }      finally      {         if(bfw!= null)//不为空要关闭资源        {           try           {              bfw.close();           }           catch(IOException io)           {}        }        if(bfw!= null)        {           try           {              bfr.close();           }           catch(IOException io)           {}        }      }   }}

5、装饰设计模式:当想要对已有的对象进行功能增强时,自定义一个类,将已有对象传入,基于已有的功能,提供加强功能,那么自定义的该类称为装饰类。

装饰类通常会通过构造方法接受被装饰的对象。并基于被装饰的对象的功能,提供更强的功能。

装饰和继承的区别:要加强某个类的某个功能,可以使用继承的方法,但是如果想要加强方法的类有很多,用继承就会使该继承体系臃肿,可扩展性也差。所以,可以找到其参数的共同类型,通过多态的形式,可以提高扩展性。

6、字节流:FileInputstream,FileOutPutStream,BufferedInputStream,BufferedOutputStream。

练习拷贝图片文件:

package cn.itheima.io; import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException; public class CopyPicture {    public static void main(String[] args){       FileOutputStream fos = null;       FileInputStream fis = null;       try {           fos = new FileOutputStream("2.bmp");           fis = new FileInputStream("1.bmp");                     byte[] buf = new byte[1024];           int len = 0;           while((len = fis.read(buf))!=-1){              fos.write(buf,0,len);           }       } catch (IOException e) {           e.printStackTrace();       }finally{           try {              if(fis!=null)                  fis.close();           } catch (IOException e) {              e.printStackTrace();           }           try {              if(fos!=null)                  fos.close();           } catch (IOException e) {              e.printStackTrace();           }       }    }}

7、转换流:OutputStreamWriter,InputStreamReader。

       这是字符流通向字节流的桥梁。

8、流操作的基本规律

明确源和目的。

       源:输入流。InputStream  Reader

       目的:输出流。OutputStreamWriter

操作的数据是否是纯文本。

       是:字符流。

       不是:字节流。

再通过设备来明确要使用哪个具体的对象:

       源设备:

       键盘System.in,硬盘 FileStream, 内存 ArrayStream.

目的设备:

       控制台System.out,硬盘 FileStream,内存ArrayStream。

 

9、File

FIle用来将文件或者文件夹封装成对象,方便对文件与文件夹的属性信息进行操作,File对象可以作为参数传递给流的构造函数。

1、File常用方法

*创建。

booleancreateNewFile();//f.createNewFile()在指定位置创建该对象的文件,如果该文件已经存在,则不创建,返回false;这跟输出流不一样,输出流对象一建立就创建文件,而且文件已经存在,会覆盖。static File createTempFile()//创建临时文件。boolean mkdir();//创建一级文件夹目录boolean mkdirs();//创建多级文件夹目录

*删除。

boolean delete();//f.delete()删除失败返回假void deleteOnExit();//f.deleteOnExit()程序退出时删除文件,常在临时文件时使用。不管有没有异常都删除
*判断。

boolean canExecute();//判断文件是否可以执行boolean exists();//判断该文件是否存在,未执行创建方法是不存在的boolean isAbsolute();//也是可以判断出来的创建方法判断是否是绝对路径,这个文件对象不执行boolean isDirectory();//判断是否为文件目录(文件夹),需要先判断是否存在boolean isFile();//判断是否为文件,需要先判断是否存在boolean isHidden;//  判断是否为隐藏文件

*获取信息。

getName();//获取文件对象名字getPath();//获取文件对象的路径,对象里封装什么路径就得到什么路径,getParent();//该方法返回的是绝对路径中的父目录,如果获取的是相对路径,返回null,如果相对路径中有上一层目录那么该目录就是返回结果。也就是说,该方法返回的是文件对象中封装的除去本文件的上层目录。getAbsolutePath();//获取文件的绝对路径,不管对象中有没有封装都获取long lastModified();//获取上次修改时间long length(); //获取文件大小。

注意:创建文件对象之后,文件并没有存在,必须执行创建方法,文件才会存在。

2、 File对象功能--文件列表

static File[] listRoots();//File.listRoots返回的是文件数组File[],返回的是电脑中有效盘符。String[] list();//f.list()//列出当前目录下所有文件,包含隐藏文件。返回的是String[]。

3、 File对象功能--文件列表2

String[] list(FilenameFilter filter);//用于过考虑给定文件夹下的符合条件的文件,FilenameFilter是一个文件过滤接口File dir = newFile("d:\\java1223\\day18");String[] arr =dir.list(new FilenameFilter(){//这是一个匿名内部类,实现FilenameFilter接口,              public boolean accept(Filedir,String name){                     returnname.endsWith(".bmp");//这个条件,将只能返回d:\\java1223\\day18目录下含有.bmp的文件              }              });File[] listFiles();//返回的是对象列表,实际开发中,使用这一个。返回指定目录下的文件对象。但是只能拿当前目录下的东西

4、列出目录下所有内容--递归

也就是函数自身调用自身,这种表现形式,或者叫编程手法,成为递归。

递归注意事项:

*限定条件

*要注意递归的次数,尽量避免内存溢出。

递归举例:

//列出指定文件夹下的所有文件,包括子文件夹下的所有文件public voidshowDir(File dir){       System.out.println(dir);       File[] files = dir.listFiles();       for(int x = 0;x<files.length;x++){              if(files[x].isDirectory())                     showDir(files[x]);              else                     System.out.println(files[x]);        }}******************************************//sum =1+2+3+4.....+(sum-1)+sum;public intgetSum(int n){       if(n==1)              return 1;       return n+getSum(n-1);} ******************************//十进制转为二进制的代码简化public voidtoBin(int num){       if(num>0){              toBin(num/2);              System.out.println(num%2);       }    } ********************************************* //列出目录下所有内容--带层次public  String getLevel(int level){       StringBuilder sb = new StringBuilder();       for(int x = 0; x<level,x++){              sb.append("  ");       }       sb.append("|--");       return sb.toString();} //列出指定文件夹下的所有文件,包括子文件夹下的所有文件public voidshowDir(File dir,int level){       System.out.println(getLevel(level)+dir.getName());       level++;       File[] files = dir.listFiles();       for(int x = 0;x<files.length;x++){              if(files[x].isDirectory())                     showDir(files[x],level);              else                     System.out.println(getLevel(level)+files[x]);        }}

删除带内容的目录

删除原理:在windows中,删除目录从里面往外删除的。

既然是从里往外删除,就需要用到递归。

public void removeDir(File dir){File[] files = dir.listFiles();for(int x = 0;x<fils.length;x++){if(files[x].isDirectory()){removeDir(files[x]);}elseSystem.out.println(files[x].toString()+":file:"+files[x].delete());}System.out.println(dir+":dir:"+dir.delete());}