黑马程序员——Java中的IO流

来源:互联网 发布:麦可风淘宝购买 编辑:程序博客网 时间:2024/05/01 09:48


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



IO流操作 


Java中,将这种通过不同输入输出设备(键盘、内存、显示器、网络等)之间的数据传输抽象表述为“流”,程序允许通过流的方式与输入输出设备进行数据传输。 

Java中的“流”都位于java.io包中,称为IO(输入输出)流。

按照操作数据的不同分为:字节流和字符流。

按照数据传输方向不同分为:输入流和输出流。

 


 

System:类中的方法和属性都是静态的。

out:标准输出,默认是控制台。

in:标准输入,默认是键盘。


字节流:

      在计算机中,无论是文本、图片、音频还是视频,所有的文件都是以二进制形式存在,IO流中针对字节的输入输出提供了一系列的流,统称为字节流。 


字节流两个基类:

InputStream:数据通过InputStream从源设备输入到程序。

OutputStream:通过OutputStream从程序输出到目标设备,从而实现数据的传输。



 

FileInputStream:它是操作文件的字节输入流,专门用于读取文件中的数据。

FileOutputStream:它是操作文件的字节输出流,专门用于把数据写入文件。 


 


字符流两个基类:

Reader  Writer

字符流:

      由于计算机中的数据基本都保存在硬盘的文件中,因此操作文件中的数据是一种很常见的操作,在操作文件时,最常见的就是从文件中读取数据并将数据写入文件,即文件的读写。

 


 

既然IO流是用于操作数据的

那么数据的最常见体现形式是:文件。 


例:

需求:在硬盘上,创建一个文件并写入一些文字数据。

找到一个专门用于操作文件的Writer子类对象,FileWriter,后缀名是类名。

前缀名是该流对象的功能。 


import java.io.*;

class FileWriterDemo

{

      public static void main(String[] args)throws IOException

      {

             //创建一个FileWriter对象,该对象一被初始化就必须要明确被操作的文件。

             //而且该文件会被创建到指定目录下。如果该目录下已有同名文件,将被覆盖。

             //其实该步就是在明确数据要存放的目的地。

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

             //调用write方法,将字符串写入到流中。

             fw.write("agdjgdh");

             //刷新流对象中的缓冲中的数据。

             //将数据刷到目的地中。

             fw.flush();

             //关闭流资源,但是关闭之前会刷新一次内部缓冲中的数据。

             //将数据刷到目的地中。      

            //closeflush的区别:

             //flush刷新后,流可以继续使用,close刷新后,会将流关闭。

             fw.close();

      }

}


读取文件在内存中的表现:




  

拷贝文本文件图例: 



 IO包中提供两个带缓冲的字节流,分别是BufferedInputStreamBufferedOutputStream,这两个流都使用了装饰设计模式。


字符流缓冲流,分别是BufferedReaderBufferedWriter,它们可以提高读写效率。

缓冲区的出现是为了提高流的操作效率而出现的。

所以在创建缓冲区之前,必须要先有流对象。

该缓冲区中提供了一个跨平台的换行符:newLine();

JDK提供了一个可以跟踪行号的输入流:LineNumberReader,它是BufferedReader的直接子类。

JKD中提供了两个类可以将字节流转换为字符流,它们分别是InputStreamReaderOutputStreamWriter。转换流是一种包装流。

 


 


记住:只要用到缓冲区,就要记得刷新。

bufw.flush();

         其实关闭缓冲区,就是在关闭缓冲区中的流对象。

             bufw.close(); 


注意:在使用转换流时,只能针对操作文本文件的字节流进行转换,如果字节流操作的是一张图片,此时转换为字符流就会造成数据丢失。 


字符读取流缓冲区:

该缓冲区提供了一个一次读一行的方法readLine(),方便于对文本数据的获取。

当返回null时,表示读到文件末尾。

readLine方法返回的时候只返回回车符之前的数据内容,并不返回回车符。 


例:

           通过缓冲区复制一个.java文件。

import java.io.*;

class CopyTextByBuf

{

                 publicstatic void main(String[] args)

                 {

                    BufferedReaderbufr = null;

                    BufferedWriterbufw = null;

                    try

                    {

                           bufr= new BufferedReader(new FileReader("BufferedWriterDemo.java"));

                           bufw= new BufferedWriter(new FileWriter("bufWriter_copy.txt"));

                           Stringline = null;

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

                           {

                                  bufw.write(line);

                                  bufw.newLine();//换行

                                  bufw.flush();

                           }

                    }

                    catch(IOException e)

                    {

                           thrownew RuntimeException("读写失败!");

                    }

                    finally

                    {

                           try

                           {

                                  if(bufr!= null)

                                         bufr.close();

                           }

                           catch(IOException e)

                           {

                                  thrownew RuntimeException("读写缓冲失败!");

                           }

                           try

                          {

                                  if(bufw!= null)

                                         bufw.close();

                           }

                           catch(IOException e)

                           {

                                  thrownew RuntimeException("写入缓冲失败!");

                           }                  

                       }

                 }

}

 


装饰设计模式:


当想要对已有的对象进行功能增强时,

可以定义类,将已有对象传入,基于已有的功能,并提供加强功能。

那么自定义的该类称为装饰类。

装饰类通常会通过构造方法接收被装饰的对象。

并基于被装饰的对象的功能,提供更强的功能。 


装饰和继承的区别:


未优化之前的体系:

MyReader//专门用于读取数据的类。

                 |--MyTextReader

                    |--MyBufferedReader

                 |--MyMediaReader

                    |--MyBufferedMediaReader

                 |--MyDataReader

                    |--MyBufferedDataReader 


class MyBufferedReader

{

                 MyBufferedReader(MyTextReadertext)

                 {}

                 MyBufferedReader(MyMediaReadermedia)

                 {}

}


上面这个类扩展性很差。

找到其参数的共同类型,通过多态的形式,可以提高扩展性。

class MyBufferedReader extends MyReader

{

                 privateMyReader r;

                 MyBufferedReader(MyReaderr)

                 {}

}


 


优化后的体系:装饰模式

MyReader//专门用于读取数据的类。

                 |--MyTextReader

                 |--MyMediaReader

                 |--MyDataReader 


装饰和继承的区别:


装饰模式比继承要灵活,避免了继承体系臃肿。

而且降低了类与类之间的关系。

装饰类因为是增强已有对象,具备的功能和已有的是相同的,只不过提供了更强功能。

所以装饰类和被装饰类通常是都属于一个体系中的。 


例:演示mp3的复制,通过缓冲区。

import java.io.*;

class CopyMp3

{

                 publicstatic void main(String[] args) throws IOException

                 {

                    longstart = System.currentTimeMillis();

                    copy_1();

                    longend = System.currentTimeMillis();

                    System.out.println((end-start)+"毫秒");

                 }

           publicstatic void copy_2() throws IOException

           {

                    MyBufferedInputStreambufis = new MyBufferedInputStream(new FileInputStream("c:\\0.mp3"));

                    BufferedOutputStreambufos = new BufferedOutputStream(new FileOutputStream("c:\\1.mp3"));

                    intby = 0;

                    while((by= bufis.myRead()) != -1)

                    {

                           bufos.write(by);

                    }

                    bufos.close();

                    bufis.myClose();

              }

 


读取键盘录入 


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

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


获取键盘录入对象。

//InputStream in = System.in;


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

InputStreamReader isr = newInputStreamReader(in);


//为了提高效率,将字符串进行缓冲区技术高效操作,使用BufferedReader


键盘录入最常见写法。

BufferedReader bufr = newBufferedReader(new InputStreamReader(System.in)); 


流操作的基本规律:

最痛苦的就是流对象有很多,不知道该用哪一个。


通过三个明确来完成。


1、明确源和目的。

                 源:输入流。InputStream Reader

                 目的:输出流。OutputStream Writer


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

                 是:字符流。

                 不是:字节流。


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

                 通过设备来进行区分:

                 设备:内存 硬盘 键盘

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

 

IO包中提供了一个PrintStream类,它提供了一系列用于打印数据的print()ptintln()方法,被称作打印流。

PrintStream可以实现将基本数据类型的数据或引用数据类型的对象格式化成字符串后再输出。

0 0
原创粉丝点击