黑马程序员_学习日记九_IO一

时间:2022-06-29 11:36:58

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

IO流概述

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

    流按数据分为:字节流和字符流。按流向分为:输入流和输出流。

IO流-FileWriter

    字节流包括两个抽象父类:InputStream和OutputStream。

    字符流也包括两个抽象父类:Reader和Writer。

    字符流 Writer类:

    该类是写入字符流的抽象类。该类的构造方法只有子类能够调用。

    1.void write(String str),该方法比较常用,向流对象的缓冲区中写入字符串。IO流适用于操作数据,而数据的最直接体现形式就是文件,在Writer类的子类OutputStream Writer中,有一个子类叫FileWriter类,是专门用于操作文件的一个类。该类实例化对象的时候,一定要有被操作的文件存在作为构造方法的参数。

    步骤一:创建一个FileWriter对象,该对象一被初始化就必须要明确被操作的文件,而且该文件会被创建到默认的路径下。

    FileWriter fw = new FileWriter(“demo.txt”);

    该语句执行后,会在默认路径下自动创建一个demo.txt的文件,如果该路径下有同名文件,将被创建的文件所覆盖。

    步骤二:调用父类的writer()方法,将数据写入到流对象的缓冲中。    fw.writer(“hello,java.”);

    步骤三:调用父类的flush()方法,该方法刷新该流对象的缓冲,即将流对象中存放的数据写到创建的文件中。

    fw.flush();

    步骤四:调用close()方法关闭流对象,释放资源。

    2.void flush(),将流对象中的数据写入文件中。调用此方法之后流对象没有关闭。

    3.void close(),将流缓冲中的数据写入文件并且关闭流对象。注意:数据写完之后一定要调用本方法将流对象关闭。

    上面几个方法都会抛出IOException异常。

IO异常处理方式

    由于Writer类的方法都会抛出IOException异常,所以如何处理异常就变得非常重要。看异常处理标准代码:

    FileWriter fw = null;

    try

    {

        fw = new FileWriter(“demo.txt”);

        fw.write(“hello,java.”);

    }

    catch(IOException e)

    {

        System.out.println(e.toString());

    }

    finally

    {

        try

        {

            if(fw != null)

                fw.close();

        }

        catch(IOException e)

        {

            System.out.println(e.toString());

        }

    }

    注意三点:

    1.语句FileWriter fw = null;一定要定义在try语句块之外作为全局变量,否则的话finally语句块中就会报错。

    2.由于close()这个方法一定要执行,所以把它单独放在finally语句块中。

    3.然而close()这个方法也会抛出IO异常,所以在finally语句块中也要同try{} catch(){}语句对异常进行处理。

IO流-文件的续写

    假如已经存在一个文件,那么如何在不覆盖该文件的情况下向文件里面写入数据呢?

这是就要调用FileWriter类的构造方法的另一个重载形式,就是:

    FileWriter(String fileName, boolean append),根据给定的文件名以及是否写入数据的boolean值来构造类对象。如果append为true,那么就将数据写入文件末尾处。

IO流-Reader-文本文件读取

    如何从一个已经存在的文件当中读取数据呢?相对应的字符流Reader类提供了一些方法。

    Reader类也是个抽象类,在这个类的子类InputStreamReader类中,有一个子类叫FileWriter类,是专门用于读取文本文件的一个类。该类实例化对象的时候,一定要有被操作的文件存在作为构造方法的参数。

    文本文件的读取方式一:读取单个字符

    步骤一:创建一个文件读取流对象,和指定的文件相关联,要保证该文件存在,如果不存在,就会抛FileNotFoundException。

    FileReader fr = new FileReader(“demo.txt”);

    步骤二:调用读取流对象的读取方法,即read()方法。这个方法读取字符时,是一次只读取一个字符,而且会自动往下读取。当文件中的数据全部读取完时,则返回-1。

    int ch = 0;

    while((ch = fr.read()) != -1)

    {

        System.out.println((char)ch);

    }

    步骤三:调用close()方法关闭流对象,释放资源。

    文本文件读取方式二:读取字符数组

    Reader类中的read()方法的重载方法:int read(char[]char),该方法从指定的文本文件中读取一个字符数组。注意:该方法返回的是读取到的字符个数,当文件中的数据全部读取完时,则返回-1。

    步骤一:创建一个文件读取流对象,和指定的文件相关联。

    FileReader fr = new FileReader(“demo.txt”);

    步骤二:定义一个字符数组,用于存储读到的字符。长度一般定义为1024。

    char[] char = new char[1024];

    步骤三:打印字符数组

    int num = 0;

    while((num = fr.read(char)) != -1)

    {

        System.out.println(new String(char, 0 ,num));

    }

    num的作用是存储读取字符数组的个数,new String()这个方法是将字符数组转换成字符串对象打印,从角标为0开始,打印的长度为num,即读取到字符数组的个数。

    步骤四:调用close()方法关闭流对象,释放资源。

    fr.close();

    两种读取方式的总结:这两种文本文件读取方式第二种方式相对效率较高。

IO流-复制文本文件

    复制文本文件其实就是将A目录下的文件数据存储到默认的B下。

    方法一:读取单个字符就存储

    步骤一:在A目录下创建一个文件,用于存储被复制文件中的数据,

    FileWriter fw = new FileWriter(“hello,java.txt”);

    步骤二:定义读取流和A目录下的文件向关联,

    FileReader fr = new FileReader(“hello,java.txt”);

    步骤三:通过不断的读写操作完成数据存储,

    int char = 0;

    while((char = fr.read()) != -1)

    {

        fw.write(char);//将读取到的字符一个一个存储到目标文件中

        fw.flush();

    }

    步骤四:调用close()方法关闭流对象。

    fr.close();

    fw.close();

    方法二:读取完所有字符再存储

    FileReader fr = null;

    FileWriter fw = null;

    try

    {  

        int num = 0;

        char[] char = new char[1024];

        fw = new FileWriter(“hello,java.txt”);

        fr = new FileReader(“hello,java.txt”);

        while((num = fr.read(char)) != -1)

        {

            fw.write(char, 0, num);

            //fw.flush();

        }

    }

    catch(IOException e)

    {

    }

    finally

    {

        if(fr != null)

        try

        {

                fr.close();

        }

        catch(IOException e)

        {

        }

        if(fw != null)

        try

        {

                fw.close();

        }

        catch(IOException e)

        {

        }

    }

IO流-BufferWriter

    字符流的缓冲区的出现提高了对数据读写的效率,相应的io包中字符流也提供了相应的缓冲区类:BufferWriter类和BufferReader类。这两个类的出现在流的基础上对流的功能进行了增强。在实际的开发过程中,一般都会加入缓冲区提高对数据操作的效率。

    BufferWriter类是Writer类的一个子类,该类对象将文本写入字符输出流,再缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。

        BufferWriter类是为了提高流的操作效率而出现的,所以在创建缓冲区之前,必须要先有写入流对象作为参数。

    步骤一:创建一个字符写入流对象,

        FileWriter fw = newFileWriter();

    步骤二:为了提高字符写入流的写入效率,加入了缓冲区。创建一个写入流缓冲区对象,再将需要被提高效率的流对象作为参数传递给缓冲区的构造方法即可,

        BufferWriter bw =new BufferWriter(fw);

    步骤三:再调用字符缓冲区对象的write()方法,将数据写入到缓冲区中,

        bw.write(“hello,java.”);

    步骤四:关闭字符流缓冲区对象(关闭字符流缓冲区对象,其实就是在关闭字符流对象)。

        bw.close();

    在BufferWriter类中还有一个void newLine()方法,该方法的作用就是换行,返回回车符之前的文本数据,并不返回回车符。并且能够跨平台执行。

IO流-BufferReader

    同理,为了提高字符流读数据时的效率io包中也提供了BufferReader类。

    BufferReader类是Reader类的一个子类,该类对象从字符输入流中读取文本, 再缓冲各个字符,从而实现字符、数组的高效读取。同样,该类的构造方法需要传入一个字符流读取流对象作为参数。

    步骤一:创建一个字符读取流对象,与某个文本文件相关联,

        FileReaderfr = new FileWriter(“hello,java.txt”);

    步骤二:创建一个读取流缓冲区对象,将需要被提高效率的读取流对象作为参数传递给缓冲区的构造方法,

        BufferReader br = BufferReader(fr);

    步骤三:调用字符缓冲区对象的read()方法,将数据写入到缓冲区中。

        br.read();

    步骤四:关闭字符流缓冲区对象(关闭字符流缓冲区对象,其实就是在关闭字符流对象)。

        bw.close();

    在BufferReader类中提供了一个readLine()的方法,该方法读取一个文本行,返回值为String,如果已达到文本的末尾,则返回null。这个方法更加提高了读取文本文件的效率。

IO流-装饰设计模式

    装饰设计模式:当想要对已有的对象进行功能增强时,可以定义一个类,将已有对象作为参数传入,基于已有对象的功能,提供加强功能。自定义的类就成为装饰类。

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

    其实BufferReader和BufferWriter其实就是两个按照装饰设计模式设计出来的装饰类。

IO流-装饰和继承的区别

    装饰设计模式比继承更加灵活,避免了集成体系带来的臃肿。而且降低了类与类之间的关系。

装饰类因为要增强已有对象,具备的功能和已有的对象时相同的,只不过在此基础将对象的功能加强了。所以装饰类和被装饰类通常都属于一个体系中。

IO流-LineNumberReader

    BufferReader类有个子类叫做LineNumberReader类,跟踪行号的缓冲字符读取流。此类定义了方法setLineNumber(int)和getLineNumber()。

    1.void setLineNumber(int number),设置指定行号的int值。

    2.int getLineNumber(),获取当前行号并返回。

IO流-字节流File  读写操作

    字节流包括两个抽象父类:OutputStream和InputStream。

    OutputStream类是抽象类,表示输出字节流的所有类的父类。这个类中的方法和Write类中的方法基本相似。但是Write类操作的是字符数组,而OutputStream类操作的是字节数组。

    OutputStream类中的子类FileOutputSteam子类就类似于FileWriter类。但是有一个区别:FileOutputSteam类没有提供flush()方法,该字节流对象在调用write方法之后并不需要刷新,即不需要调用flush()。因为FileOutputSteam字节流对象底层是直接对字节进行操作的。示例代码如下:

        FileOutputStreamfos = new FileOutputStream(“hello,java.txt”);

        fos.write(“hello.java”.getBytes[]);//因为操作的是数据时字节数组,所以字符串对象调用getBytes[]方法将字符串转化为字节数组。

        fos.close()

    同理,InputStream类也是抽象类,该抽象类是所有字节输入流类的父类。InputStream类中的FileInputStream类就类似于FileReader类。但也有其特殊方法:int available()。

IO流-读取键盘录入

    如何读取键盘输入的数据呢?

    在System类中有个in字段,该字段叫标准输入流,是一个InputStream类的流对象,该对象接收对应于键盘或者用户指定的其他输入源。

    示例:接收键盘输入的一行字符并打印。

        InputStreamin = System.in;

        StringBulildersb = new StringBuilder();//定义一个字符串缓冲区,用于接收读取到的字符

        while(true)

        {

             int char = in.read();

             if(char == ’\r’)

                 continue;

             if(char == ’\n’)

                 {

                     String str = sb.toString();

                     if(“over”.equals(str))
                         break;

                    System.out.println(str.toString());

                 } 

             sb.append((char)char);

          }

IO流-InputStreamReader-读取转换流

    接收键盘输入的一行字符,上面的代码其实和字符读取流BufferReader类中的readLine()方法很类似。因为readLine()方法是字符流BufferedReader类中的方法。那么,能不能将字节流转换成字符流后,再去调用字符流中的readLine()方法呢?

    在字符流抽象类Reader中有个子类叫做InputStreamReader类,该类就是字节流通向字符流的桥梁。该类中的构造方法需要一个字节流对象作为参数传递进去。

    示例代码:

        InputStreamin = System.in;//接收键盘录入数据

        //将字节流对象转换成字符流对象,使用转换流:InputStreamReader()

        InputStreamReaderisr = new InputStreamReader(in);

        //为了提高读写效率,将字符串进行缓冲区技术包装,使用BufferedReader类

        BufferedReaderbr = new BufferedReader(isr);

        Stringstr = null

            while((str= br.readLine()) != null)

                {

                    if(“over”.equals(str))

                        break;

                    else

                        System.out.println(str.toString());

    

                 }

           Br.close();

IO流-OutputStreamWriter-写入转换流

    同样的,在字符流抽象类Writer中,提供了将字符流转换成字节流的类:OutputStreamWriter类,该类是字符流通向字节流的桥梁。

IO流-流操作规律

流操作的基本规律:通过三个明确来完成

1.明确数据的来源和数据的目的,

     来源:输入流(InputStream、Reader)

     目的:输出流(OutputStream、writer)

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

     是:字符流

     不是:字节流

3.当体系明确后,再明确要使用哪个具体的对象。

  通过设备来进行区分:

     来源设备:内存,硬盘,键盘

     目的设备:内存,硬盘,控制台

IO流-改变标准输入输出设备

    System这个类中有两个方法可以改变标准的输入和输出设备.

    1.staticvoid setIn(InputStream in),重新设置“标准”输入流

    2.staticvoid setout(PrintStream out),重新设置“标准”输出流

IO流-异常的日志信息

    可以将System类中通过getProperties()方法获取到的系统信息打印到指定文件中,由于这个方法返回的是一个Properties类对象,而这个对象中提供了一个方法叫void list(PrintStreamout),将属性列表输出到指定的输出流。

         Propertiespro = System.getPropertiesi();

         pro.list(newPrintStream(“system_info.txt”));

    这样就可以把系统信息保存到一个文件当中方便以后查看。

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

详细请查看:http://edu.csdn.net/heima