黑马程序员 IO流

来源:互联网 发布:安卓时间网络同步不 编辑:程序博客网 时间:2024/06/11 20:04
---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------

1.  IO的概述和File方法

IO流用来处理设备之间的数据传输
       Java对数据的操作是通过流的方式
       Java用于操作流的对象都在IO包中

File类在整个IO包中与文件本身有关的操作类,所有的与文件本身有关指的是创建、删除文件等操作。在java.io包中的File类本身是一个跨平台的文件操作类,所以在操作中要更多的考虑到各个操作系统的区别。

File 即指文件也指文件夹。

File类构造方法和字段摘要

staticString pathSeparator  路径分隔符,window下是";"。

staticchar pathSeparatorChar   路径分隔符,window下是";"。

staticString separator  路径分隔符,window下是"\"。

staticchar separatorChar  路径分隔符,window下是"\"。

File(Fileparent, String child) 根据 parent 抽象路径名和 child 路径名字符串创建一个新 File 实例。

File(Stringpathname)  通过将给定路径名字符串转换为抽象路径名来创建一个新 File 实例。

File(Stringparent, String child) 根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。

File(URIuri)  通过将给定的 file: /URI 转换为一个抽象路径名来创建一个新的 File 实例。

File的相关方法

StringgetName():返回文件名或路径名(若是路径,返回最后一级子路径名)

StringgetPath():返回对象对应的路径名

File  getAbsoluteFile():返回绝对路径

StringgetAbsolutePath():返回对象对应的绝对路径

StringgetParent():返回文件目录的上一级目录名

booleanrenameTo(File newName):重命名此File对象对应的文件或目录,若重命名成功返回true;

booleanexists():判断对象对应的文件或目录是否存在;

booleancanWrite():判断对象对应文件或目录是否可写;

booleancanRead():判断对象对应文件或目录是否可读;

booleanisFile():判断对象是文件,不是目录;

booleanisDirectory()  判断对象的文件是否是一个目录;

booleanisAbsolute() 判断对象对应文件或目录是否为绝对路径名;

booleancreateNewFile() 当且仅当不存在,该方法创建一个该File对象所指定的新文件,创建成功返回true。

booleandelete():删除File对象所对应的文件或路径;

booleanmkdir() 创建File对象所对应的目录,调用该方法的File对象必须对应路径,而不是文件。

String[]list():列出File对象的所有子文件名和路径名。

File[]listFiles():列出File对象的所有子文件和路径。

staticFile[] listRoots():列出系统所有的根路径;

 

2.  递归

现在要求输出一个给定目录中的全部文件的路径。

本程序肯定只能依靠递归的操作完成,因为在一个给定的路径下有可能还是文件夹,那么如果是文件夹的话则肯定要继续列出,重复判断。

递归:程序调用自身的编程技巧

递归就是在方法里调用自身;

在使用递归时,必须有一个明确的递归结束条件,称为递归出口。

 

3.  文件过滤器java.io.FilenameFilter

File 类里有方法: String[] list(FilenameFilterfilter)    返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中满足指定过滤器的文件和目录。 

FilenameFilter(文件过滤器)该接口里包含accept(File dir,String name)方法,该方法依次对指定File的所有子目录,子文件夹进行迭代。

dir - 被找到的文件所在的目录。

name - 文件的名称。

当且仅当该名称应该包含在文件列表中时返回 true;否则返回 false

Eg

public class Demo {

   public static void main(String[] args) {

     

      File f = new File("D:/V5");

      deleter(f);

     

      System.out.println("删除成功 !");

   }

   public static void deleter(File f){//程序简陋,就没有判断空引用!

      if(f.isFile()){

        f.delete();

      }else if(f.isDirectory()){

        //过滤器

        File []file = f.listFiles(new FilenameFilter(){

           public boolean accept(File dir, String name) {

returnname.endsWith(ext);// 真正起作用的还是这里的ext

           }

});

        for (File file2 : file) {

           deleter(file2);//调用自身,递归!

           file2.delete();//删除子文件夹(内部没有文件的时候可以删除),如果这里写上f.delete();那么V5这个文件夹也没有了

        }

      }

   }

}

 

4.  IO流的分类

从不同角度分类:

流动方向的不同可以分为输入流和输出流;

处理数据的单位不同分为字节流和字符流;

功能的不同可分为节点流和处理流;

      节点流:直接操作目标设备,例如:磁盘或一块内存区域。

      处理流:通过操作节点流,从而间接完成输入或输出功能的流。处理流是的存在是建立在一个已经存在的输入流或输出流的基础之上的。

所有流都继承于以下四种抽象流类型的某一种:(抽象流)

 

 

5.  字节流

InputStream:是表示字节输入流的所有类的超类。

FileInputStream:从文件系统中的某个文件中获得输入字节。哪些文件可用取决于主机环境。FileInputStream 用于读取诸如图像数据之类的原始字节流。要读取字符流,请考虑使用 FileReader。

FilterInputStream:包含其他一些输入流,它将这些流用作其基本数据源,它可以直接传输数据或提供一些额外的功能。

BufferedInputStream:该类实现缓冲的输入流。

Stream: ObjectInputStream: PipedInputStream:

OutputStream:此抽象类是表示输出字节流的所有类的超类。

FileOutputStream:文件输出流是用于将数据写入 File 或 FileDescriptor 的输出流。

FilterOutputStream:此类是过滤输出流的所有类的超类。

BufferedOutputStream:该类实现缓冲的输出流。

PrintStream:DataOutputStream:

ObjectOutputStream:PipedOutputStream:

 

6.  字符流

Reader:用于读取字符流的抽象类。子类必须实现的方法只有 read(char[], int, int) 和 close()。

BufferedReader:从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。 可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了。

LineNumberReader:跟踪行号的缓冲字符输入流。此类定义了方法 setLineNumber(int)getLineNumber(),它们可分别用于设置和获取当前行号。

InputStreamReader:是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。

FileReader:用来读取字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是适当的。要自己指定这些值,可以先在 FileInputStream 上构造一个 InputStreamReader。

     CharArrayReader:

     StringReader:

Writer:写入字符流的抽象类。子类必须实现的方法仅有 write(char[], int, int)、flush() 和 close()。

BufferedWriter:将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。

OutputStreamWriter:是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。

FileWriter:用来写入字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是可接受的。要自己指定这些值,可以先在 FileOutputStream 上构造一个 OutputStreamWriter。

     PrintWriter:

     CharArrayWriter:

     StringWriter:

Eg

练习 :读取一个.java文件。并打印在控制台上。     

FileReader fr=null;

char[] buf=new char[1024];

int num=0;

try {

    fr= newFileReader("a.txt");

    try {

         while((num=fr.read(buf))!=-1){

              System.out.print(newString(buf,0,num));

         }

    } catch(IOException e) {

          e.printStackTrace();

    }

    } catch(FileNotFoundException e) {

          e.printStackTrace();

    }

    finally

    {

          try {

              if(fr!=null)

                   fr.close();

          } catch(IOException e) {

                   e.printStackTrace();

          }               

    }

练习2:将C盘的一个文本文件拷贝到D盘(数组相当于存储之中的媒介)

步骤:新建一个文件用于存储要被拷贝的文件

2.定义读取流和源文件关联

3.通不过不断读写完成数据存储

4.关闭资源

   FileWriterfw=null;

  FileReader fr=null;

  try {

          fw=new FileWriter("b.txt");

          fr=new FileReader("a.txt");

          char[] buf=new char[1024];

          int num=0;

          while ((num=fr.read(buf))!=-1){

                  fw.write(buf,0,num);

          }

}

  catch (IOException e) {

        // TODO Auto-generatedcatch block

        e.printStackTrace();

}

  finally

        {

           try {

                        fr.close();

                }catch (IOException e) {

                       

                        e.printStackTrace();

                }             

           try {

                        fw.close();

                }catch (IOException e) {

                       

                        e.printStackTrace();

                }             

       }

 

7.  字符流的缓冲区

缓冲区的出现提高了对数据的读写效率

对应类: BufferWriter   BufferedReader

特点:缓冲区要结合流才可以使用,在创建缓冲区之前,必须要有流对象。在流的基础上对流的功能进行了增强。

BufferWriter步骤:

1.创建一个字符写入流对象

FileWriter fw=new FileWriter("a.txt");

2.将需要被提高效率的流对象作为参数传递给缓冲区的构造函数

bufferedWriter bufw=new BufferedWriter(fw);

buff.write("asdasdas");

bufw.newLine();//换行符,跨平台的

3.将缓冲区刷新

bufw.flush;

4.关闭缓冲区,就是在关闭缓冲区中的流对象

bufw.close();

BufferedReader步骤

1.创建一个字符写入流对象

FileReader fr=new FileReader ("a.txt");

2.将需要被提高效率的流对象作为参数传递给缓冲区的构造函数

BufferedReader bufr=new BufferedReader (fr);

3.读取流对象:该缓冲区提供了一个一次读取一行的方法。当返回null时表示,文件读到末尾

String line=null;

while((line=bufr.readLine())!=null)

{

String s=line;}

4.关闭

bufr.close();

readLine()方法的原理:

无论是读一行,获取多个字符,最终都是在硬盘上一个一个读取,最终使用额还是read方法一次读一个的方法。

自定义一个功能和readline一致的方法,来模拟下BufferedReader();

public class MyBufferedReader extends Reader {

    privateReader r;

    public MyBufferedReader(Reader r) {

            super();

            this.r= r;

    }

    //可以一次读取一行的方法

    public StringmyReadLine() throws IOException

    {

         //定义一个临时容器。StringBulider容器,应用于存储字符数组

         StringBuildersb=new StringBuilder();

         intch=0;

         while((ch=r.read())!=-1){

         if(ch=='\r')

             continue;

         if(ch=='\n')

             returnsb.toString();

         else

             sb.append((char)ch);

         }

         if(sb.length()!=0)

             returnsb.toString();

         returnnull;

         }

    }

Eg

通过缓冲区复制一个文件

BufferWriter bufw=null;

 BufferReader bufr=null;

  try {

          bufw=new BufferWriter(newFileWriter("b.txt"));

          bufr=new BufferReader(newFileReader("a.txt"));

         String line=null;

          while ((line=buffr.read(buf))!=null){

                  bufw.write(line);

                  bufw.newLine();

                 bufw.flsuh;

          }

}

  catch (IOException e) {

        // TODOAuto-generated catch block

        e.printStackTrace();

}

  finally

        {

           try {

                        fr.close();

                }catch (IOException e) {

                       

                        e.printStackTrace();

                }             

           try {

                        fw.close();

                }catch (IOException e) {

                       

                        e.printStackTrace();

                }             

        }

 

8.  装饰设计模式

当想要对已有的独享进行功能增强时,可以定义类,将已有的对象传入,基于已经有的功能,

并提供加强功能,那么自定义的该类称为装饰类

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

 

9.  LineNumberReader

带有行号的缓冲区:
LineNumberReader lnr=new LineNumberReader();
获取行号:lnr.getLineNumber();
设置行号从几开始:lnr.setLineNumber(100);
LineNumberReader 步骤
1.创建一个字符写入流对象
FileReader fr=new FileReader ("a.txt");
2.将需要被提高效率的流对象作为参数传递给缓冲区的构造函数
LineNumberReader lnfr=new LineNumberReader (fr);
3.读取流对象:该缓冲区提供了一个一次读取一行的方法。当返回null时表示,文件读到末尾
String line=null;
while((line=lnfr.readLine())!=null)
{
String s=line;
String linenum=lnfr.getLineNumber();
}
4.关闭
lnfr.close();

 

10.      异常的日志信息和系统信息

使用printStream();

输出到控制台:

System.SetOut(newPrintStream("sysinfo.txt"))

e.printStackTrace(System.out);

上面这两句就相当于

e.printStackTrace(newPrintStream("sysinfo.txt"));//将日志文件打印到文件中

获取系统信息:

 Properties prop=System.getProperties();

prop.list(System.out);//打印到控制台

prop.list(newPrintStream("sysinfo.txt"));//打印到文件中

 

11.      读取键盘录入

System.out:对应的是标准输出设备,控制台

System.in:对应的标准输入设备,键盘

代码

InputStream in=System.in;

int by=in.read();

sop(by);

结束录入

in.close();

 

12.      转换流

读取转换流:InputStreamReader

写入转换流:OutputStreamReader

读取转换流:InputStreamReader 字节流通向字符流的桥梁

步骤

1.获取键盘录入对象

Inputstream in=System.in

2.将字节流对象转换成字符流对象,使用转换流InputStreamReader

InputStreamReader isr=new InputStreamReader(in);

3.提高效率使用字符流缓冲区BufferedReader进行读取

BufferedReader bf=new BufferedReader(is);

String line=null;

while((line=bf.readLine())!=null)

{

   if("over".equals(line))

    break;

    sop(line);

}

bufr.close;

写入转换流:OutputStreamReader 字符流通向字节流的桥梁

步骤

1.获取输出对象

Outputstream out=System.out

2.将字符流对象转换成字节流对象,使用转换流OutputstreamWriter

OutputstreamWriter osw=new OutputstreamWriter(out);

3.提高效率使用字符流缓冲区BufferedWriter进行写入

BufferedWriter bw=new BufferedWriter(osw);

String line=null;

while((line=bf.readLine())!=null)

{

   if("over".equals(line))

    break;

    bw.write(line);

    bufw.newLine();

}

bufr.close;

 

13.      流操作规律

两个明确:

1.明确源和目的

   源:输入流。InputStream字节流  Reader 字符流

   目的:输出流 OutPutStream 字节流  Writer 字符流

 2.操作的数据是否是纯文本

   是 就是字符流 如果设备是键盘 就将字节流转换为字符流

   不是 就是 字节流

3.当体系明确后,在明确要是用那个具体的对象

    通过设备来区分

    源设备  内存 硬盘 键盘

    目的设备  内存  硬盘  控制台

4.是否需要提高效率  是 BufferedReader  BufferedInputStream

                   否 BuffreredWriter BufferedOutputStream

案例分析 :

1.将一个文本文件中的数据存储到另一个文件中,复制文件

  源: InputStream字节流  Reader 字符流

  是否是纯文本 是  Reader

  设备: 文件   操作文件的对象就是FileReader

  是否需要高效

  是  BufferedReader

  FileReader fr=newFileReader("a.txt");

  BufferedReaderbufr=new BufferedReader(fr);

  目的  OutPutStream 字节流  Writer 字符流

  是否是纯文本 :是 Writer

  设备: 文件 写入文件的对象 就是 FileWriter

  是否需要高效  是   BufferedWriter

  FileWriter fw=newFileWriter("b.txt");

  BufferedWriterbufw=new BufferedWriter(fw);

2.将一个图片文件数据存储到另一个文件中,复制文件。

分析

源:

 是否是纯文本 : 不是  InputStream

 设备 文件 就是 FileInputStream

  是否高效 是

 BufferedInputStream

   FileInputStreamisr=new FileInputStream("a.jpg");

   BufferedInputStream bufis=new BufferedInputStream(isr);

目的

  是否纯文本 :不是 OutPutStream

  设备:文件 FileOutPutStream

是否高效 是

 BufferedOutputStream

 FileOutPutStreamosw=new FileOutPutStream("b.jpg");

BufferedOutputStream bufos=new BufferedOutputStream(osw);

3.需求将键盘录入的数据保存到一个文件中 。

 源:键盘  字节流

  是否纯文本  Reader

  设备 :键盘  ,对应的对象时 System.in 对应的是字节流 ,为了操作方便 转成字符流

  既然明确了Reader 就将System.in 转换成字符流 InputStreamReader

  InputStreamReaderisr=new InputStreamReader(System.in);

  需要高效吗 ?

  BufferedReaderbufr=new BufferedReader(isr);

  目的: 文件

   是否纯文本 是  Writer

   设备:文件 FileWriter

   需要高效吗?

   是 BufferedWriter

4.扩展 :想要吧录入的数据按照指定的编码表(utf-8)将数据存到文件中

   目的:OutPutStream 字节流  Writer 字符流

   是否是存文本:是  Writer

   设备 :文件 fileWriter

   默认编码表是 gbk

   编码标只有转换流可以指定。所以要使用的对象是写入转换流 OutputStreamWriter

   转换流需要接受一个自己输出流,操作字节输出流的是FileOutputStream

  OutputStreamWriter osw=new OutputStreamWriter(newFileOutputStream("b.txt"),"utf-8");

  BufferedWriterbufw=new BufferedWriter (osw);

通常涉及到字符编码转换的时候,就需要用到转换流。

 

14.      Properties集合

Properties集合:是hashtable的子类,具备map集合的特点,里面存储的键值对都是字符串文件流和键值对相结合就用此集合

是集合中和IO技术相结合的集合容器

该对象的特点:可以用于键值对形式的配置文件,可以操作键盘的数据。

//设置和获取元素。

   Properties prop=new Properties();

  prop.setProperty("张三","30");//添加,修改

   sop(prop);

  prop.getProperty("键");

   循环获取

  Set<String> names=prop.stringPropertyNames();

   for(String s :names)

     {

          prop.getProperty(s);

     }

Properties存取配置文件,将文本a.txt中的数据存到集合中进行操作。

步骤:1.用一个六和info.txt关联

2.读取一行数据,用该行数据用"="尽情切割

3.封号左边作为建,右边作为值,存储到Properties集合中即可

BufferedReader bufr=new BufferedReader(newFileReader("a.txt"));

String line=null;

Properties prop =new Propertites();

while((line=bufr.readLine())!=null)

{

   String[] arr=line.split("=");

  prop.setProperty(arr[0],arr[1]);

}

简便方法

Properties prop =new Propertites();

FileInputStream fis=newFileInputStream("a.txt");

//将流中的数据加载进集合

prop.load(fis);

prop.list(System.out);

Eg

用于记录应用程序运行次数,如果使用次数已经到,就给出注册提示。

     Propertiesprop=new Properties();

     File file=newFile ("count.ini");

     if(!file.exists())

         file.createNewFile();

     FileInputStreamfis=new FileInputStream(file);

     prop.load(fis);

     int count=0;

     Stringvalue=prop.getProperty("time");

     if(value!=null)

     {

         count=Integer.parseInt(value);

         if(count>=5)

         {

            System.out.println("您使用的次数已到");

            return;

          }

     }

     count++;

     prop.setProperty("time",count+"");

     FileOutputStreamfos=new FileOutputStream(file);

     prop.store(fos,"");

     fos.close();

     fis.close();

}

 

15.      打印流和合并流(序列流)

打印流 :该流提供了打印方法,可以将各种数据类型的数据都原样打印出来。

字节打印流PrintStream

构造函数可以接受的参数类型

1.file对象 File

2.字符串路径 String

3.字节输出流OutputStream

字符打印流PrintWriter

构造函数可以接受的参数类型

1.file对象 File

2.字符串路径 String

3.字节输出流OutputStream

4.字符输出流 Writer

Eg

控制台输入后,打印在控制台

BufferedReader bufr=new BufferedReader(newInputStreamReader(System.in));

PrintWriter Out=new PrintWriter(System.in,true));

String line=true;

while((line=bufr.readLine()))!=numm

{

  if("over".equals(line))

      break;

  out.println(line);

}

out.close();

bufr.close();

 

合并流(序列流):SeaquenceInputStream 对多个流进行合并。

vactor<FileInputStream> v=newvactor<FileInputStream>();

v.add(new FileInputStream("1.txt"));

v.add(new FileInputStream("2.txt"));

v.add(new FileInputStream("2.txt"));

Enumeration<FileInputStream> en=v.elements();

SeaquenceInputStream sis=new SeaquenceInputStream(en);

FileOutputStream fos=newFileOutputStream("4.txt");

byte[] buf=new byte[1024];

int len=0;

while((len=sis.read(buf))!=-1){

fos.write(buf,0,len);

}

fos.close();

sis.close();

 

总结:

a)       File主要是对文件进行操作。

b)      读写文本有中文的话还是用字符流,因为用字节流可能会出现乱码

c)       列出文件夹中的文件时,用递归是最快捷的方式

d)      文件过滤器可以利用一定的规律过滤文件

e)       Io流主要的应用就是读取写入文件,对这一块要特别熟悉

f)       利用缓冲区可以提升文件的读写速度

g)       如果想把数据按原样写入可以使用打印流

h)      Io流也可以实现读取键盘的录入

i)        转换流可以实现字节流转换成字符流

j)        使用IO流时要明确流的操作规律

k)       使用Properties可以存储配置信息


---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------
详细请查看:www.itheima.com
0 0