黑马程序员_java基础学习IO流学习笔记

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

IO流  概述:



1IO流:即InputOutput的缩写。

2、特点:

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

        2Java对数据的操作是通过流的方式。

        3Java用于操作流的对象都在IO包中。

        4)流按操作数据分为两种:字节流和字符流。

        5)流按流向分为:输入流和输出流。

注意:流只能操作数据,而不能操作文件。

3IO流的常用基类:

        1)字节流的抽象基流:InputStreamOutputStream

        2)字符流的抽象基流:ReaderWriter

注:此四个类派生出来的子类名称都是以父类名作为子类名的后缀,以前缀为其功能;如InputStream子类FileInputStreamReader子类FileReader

 





 

IO的分类及应用


(1)IO流的四个基类
  A:字节流
   字节输入流
    InputStream
   字节输出流
    OutputStream
  B:字符流
   字符输入流
    Reader
   字符输出流
    Writer

  这四个都是抽象类。
  输入流:读取数据
  输出流:写入数据
(2)文件的写入数据
  对文本文件写入数据:
   Writer -- FileWriter
 
  FileWriter的构造方法:
   FileWriter(File file)
   FileWriter(String name)
   FileWriter(File file,boolean append)
   FileWriter(String name,boolean append)

示例:
import java.io.*; 
 
class FileWriterDemo  

    public static void main(String[] args)  
    { 
        writerDate("abcde");//写入数据  
        writerFrom("zheshi:\r\nshenma");//续写数据,并附换行操作  
    } 
 
    //在硬盘上创建一个文件并写入指定数据  
    public static void writerDate(String s) 
    { 
        FileWriter fw=null; 
        try 
        { 
            fw=new FileWriter("demo.txt");//创建文件  
            fw.write(s);//将数据写入流  
        } 
        catch (IOException e) 
        { 
            throw new RuntimeException("写入失败"); 
        } 
        finally 
        { 
            if(fw!=null) 
                try 
                { 
                    fw.close();//将写入流的数据刷到指定文件内,并关闭流资源  
                } 
                catch (IOException e) 
                { 
                } 
        } 
    } 
 
    //对已有文件的数据续写指定数据  
    public static void writerFrom(String s) 
    { 
        FileWriter fw=null; 
        try 
        { 
            fw=new FileWriter("demo.txt",true);//传递一个true参数,代表不覆盖已有的文件。  
            fw.write(s); 
        } 
        catch (IOException e) 
        { 
            throw new RuntimeException("写入失败"); 
        } 
        finally 
        { 
            try 
            { 
                if(fw!=null) 
                    fw.close(); 
            } 
            catch (IOException e) 
            { 
            } 
        } 
    } 

 


 

 

  字符输出流写入数据的基本步骤:
   A:创建字符输出流对象
   B:调用该对象的write方法
   C:释放资源

  代码体现:
   FileWriter fw = new FileWriter("fw.txt");

   fw.write("hello,io,我来了");
   fw.flush();

   fw.close();

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

示例:
import java.io.*; 
class  FileReaderDemo 

    public static void main(String[] args)  
    { 
        //第一种读取方式  
        singleCharReader(); 
        //第二种读取方式  
        arrayCharReader(); 
    } 
 
    //第一种读取方式,单个字符读取  
    public static void singleCharReader() 
    { 
        FileReader fr=null; 
        try 
        { 
             
            fr=new FileReader("demo.txt");//读取文件位置和文件名  
            for (int ch=0;(ch=fr.read())!=-1 ; ) 
            { 
                System.out.print((char)ch); 
            } 
        } 
        catch (IOException e) 
        { 
            throw new RuntimeException("读取失败"); 
        } 
        finally 
        { 
            try 
            { 
                if(fr!=null) 
                    fr.close();//关闭读取流资源  
            } 
            catch (IOException e) 
            { 
            } 
        } 
    } 
 
    //第二种读取方式,通过字符数组进行读取  
    public static void arrayCharReader() 
    { 
        FileReader fr=null; 
        char[] arr=new char[1024];//定义一个字符数组,用于临时存储读取的字符  
        try 
        { 
            //读取一个.java文件,并打印在控制台上。  
            fr=new FileReader("FileReaderDemo.java"); 
            for (int len=0;(len=fr.read(arr))!=-1 ; ) 
            { 
                //显示字符数组的字符个数  
                System.out.print(new String(arr,0,len)); 
            } 
        } 
        catch (IOException e) 
        { 
            throw new RuntimeException("读取失败"); 
        } 
        finally 
        { 
            if(fr!=null) 
                try 
                { 
                    fr.close(); 
                } 
                catch (IOException e) 
                { 
                } 
        } 
    } 

 

 

 

      flush和close的区别:
    flush刷新缓冲区,close刷新缓冲区,并释放资源。
    flush刷新缓冲区后,流对象还可以继续使用,close释放资源后,
     流对象不能被使用。

   流操作一定要调用close方法的原因:
    创建字符输出流对象的时候:不仅仅是在堆内存创建了java对象,
    并且使用了系统资源创建了文件对象,当程序结束后,java的对象
    会自动变成垃圾,被回收。 而系统的资源就一直在被使用,所以,
    我们需要调用close方法,就是去通知系统,你创建文件时候使用的
    资源可以释放了。

  两个小知识点:
   如何追加数据,而不是覆盖数据:
    使用带两个参数的构造方法,第二个参数表示是否是追加数据,写为true即可。

   数据追加或者写入的时候,如何换行:
    换行在不同的操作系统中,对应的字符不一样:
    windows: \r\n
    linux: \n

    有些软件,对不同的换行都是识别的,比如:editplus
    但是,windows自带的记事本只能识别\r\n。
   
  加入异常处理:
    public class FileReaderTest4 {
    public static void main(String[] args) {
     FileWriter fw = null;
     try {
     fw = new FileWriter("fx.txt");
     fw.write("hello,我是荣斌");
     fw.flush();
     } catch (IOException e) {
      e.printStackTrace();
     } finally {
     if(fw!=null){
     try {
     fw.close();
     } catch (IOException e) {
     e.printStackTrace();
        }
       }
      }
     }
    }
(3)文件的读取数据
  对文本文件读取数据:
   Reader -- FileReader
 
  FileReader的构造方法:
   FileReader(File file)
   FileReader(String name)

  字符输入流读取数据的基本步骤:
   A:创建字符输入流对象
   B:调用该对象的read方法
   C:释放资源

  代码体现:
  
   一次读写一个字符代码如下:
   FileReader fr = new FileReader("fw.txt");
  
   //一次读写一个字符
   int num = 0;
   while((num=fr.read())!=-1)
   {
    System.out.print((char)num);
   }

   fr.close();

   一次读写一个字符数组代码如下:
   FileReader fr = new FileReader("fw.txt");
  
   //一次读写一个字符数组
   char[] chs = new char[1024]; //1024的整数倍
   int len = 0; //存储读取的实际长度
   while((len=fr.read(chs))!=-1)
   {
    System.out.print(new String(chs,0,len));
   }

   fr.close();
(4)文件的复制
  数据源:
   来源:a.txt
   FileReader -- 读取数据
  目的地:
   目的:b.txt
   FileWriter -- 写入数据

示例:

/*
需求:
将c盘一个文本文件复制到e盘、
复制的原理:
其实就是将c盘下的文件数据存储到e盘的一个文件中。
步骤:
1、在e盘创建一个文件。用于存储c盘文件中的数据。
2、定义读取流和c盘文件关联。
3、通过不断的读写完成数据存储。
4、关闭资源。
*/ 
import java.io.*; 
  
class ReaderWriterTest 

       publicstatic void main(String[] args)  
       { 
              //调用复制方法  
              //copy_1();  
              copy_2(); 
       } 
       //用第一种读取方式进行复制  
       publicstatic void copy_1() 
       { 
              FileWriterfw=null; 
              FileReaderfr=null; 
              try 
              { 
                     //关联读取和写入的文件  
                     fw=newFileWriter("E:\\HelloWorld.java"); 
                     fr=newFileReader("C:\\HelloWorld.java"); 
                     for(int ch=0;(ch=fr.read())!=-1 ; ) 
                     { 
                            fw.write(ch);//一个字符一个字符写入  
                     } 
              } 
              catch(IOException e) 
              { 
                     thrownew RuntimeException("读写失败"); 
              } 
              finally 
              { 
                     if(fr!=null) 
                            try 
                            { 
                                   fr.close();//对读取流和写入流分别关闭  
                            } 
                            catch(IOException e) 
                            { 
                            } 
                     if(fw!=null) 
                            try 
                            { 
                                   fw.close(); 
                            } 
                            catch(IOException e) 
                            { 
                            } 
              } 
       } 
  
       //第二种读取方式进行复制  
       publicstatic void copy_2() 
       { 
              FileWriterfw=null; 
              FileReaderfr=null; 
              try 
              { 
                     //关联读取和写入的文件  
                     fw=newFileWriter("E:\\HelloWorld.java"); 
                     fr=newFileReader("C:\\HelloWorld.java"); 
                     char[]arr=new char[1024]; 
                     for(int len=0;(len=fr.read(arr))!=-1 ; ) 
                     { 
                            fw.write(arr,0,len);//利用数组一次存入数组中的字符  
                     } 
              } 
              catch(IOException e) 
              { 
                     thrownew RuntimeException("读写失败"); 
              } 
              finally 
              { 
                            try 
                            { 
                                   if(fr!=null) 
                                          fr.close(); 
                            } 
                            catch(IOException e) 
                            { 
                            } 
                            finally 
                            { 
                                   if(fw!=null) 
                                          try 
                                          { 
                                                 fw.close(); 
                                          } 
                                          catch(IOException e) 
                                          { 
                                          } 
                            }      
              } 
       } 

 

 

  3:带缓冲的字符流对象


(1)字符流体系图
  Reader 的功能
   read()
   read(char[] chs)
   close()
  
   FileReader:没有特殊方法
   BufferReader:readLine()

  Writer  的功能
   write(int ch)
   write(String str)
   write(String str,int start,int end)
   write(char[] chs)
   write(char[] chs,int start,int end)
   flush()
   close()
  
   FileWriter:没有特殊方法
   BufferedWriter:newLine()
(2)字符缓冲输出流写入数据
  代码体现:

BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));

   bw.write("哈哈,该下课了");
   bw.newLine();
   bw.flush();

   bw.close();

(3)字符缓冲输入流读取数据
  代码体现:
  
   方式1:
BufferedReader br = new BufferedReader(new FileReader("bw.txt"));

    int num = 0;
    while((num=br.read())!=-1)
    {
     System.out.print((char)num);
    }

    br.close();

   方式2:
    BufferedReader br = new BufferedReader(new FileReader("bw.txt"));

    char[] chs = new char[1024];
    int len = 0;
    while((len=br.read(chs))!=-1)
    {
     System.out.print(new String(chs,0,len));
    }

    br.close();
   方式3:
    BufferedReader br = new BufferedReader(new FileReader("bw.txt"));

    String line = null;
    while((line=br.readLine())!=null)
    {
     System.out.println(line);
    }

    br.close();
 
(4)字符缓冲流复制文本文件
示例:

/*
需求:使用缓冲技术copy一个文本文件
*/ 
import java.io.*; 
 
class BufferedCopyDemo  

    public static void main(String[] args)  
    { 
         
        BufferedWriter bfw=null; 
        BufferedReader bfr=null; 
        try 
        { 
            //创建写缓冲对象  
            bfw=new BufferedWriter(new FileWriter("ReaderWriterTest_copy.txt")); 
            //创建读缓冲对象  
            bfr=new BufferedReader(new FileReader("ReaderWriterTest.java")); 
            //利用BufferedReader提供的readLine方法获取整行的有效字符。直到全部获取  
            for (String line=null; (line=bfr.readLine())!=null; ) 
            { 
                bfw.write(line);//写入指定文件中  
                bfw.newLine();//换行  
                bfw.flush();//将缓冲区数据刷到指定文件中  
            } 
             
        } 
        catch (IOException e) 
        { 
            throw new RuntimeException("文件copy失败"); 
        } 
        finally 
        { 
            if(bfw!=null) 
                try 
                { 
                    bfw.close();//关闭写入流  
                } 
                catch (IOException e) 
                { 
                    throw new RuntimeException("写入流关闭失败"); 
                } 
            if(bfr!=null) 
                try 
                { 
                    bfr.close();//关闭读取流  
                } 
                catch (IOException e) 
                { 
                    throw new RuntimeException("读取流关闭失败"); 
                } 
        } 
    } 

 

装饰设计模式

1、简述

        当想对已有对象进行功能增强时,可定义类:将已有对象传入,基于已有对象的功能,并提供加强功能,那么自定义的该类称之为装饰类。

2、特点

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

3、装饰和继承的区别:

        1)装饰模式比继承要灵活。避免了继承体系的臃肿,且降低了类与类之间的关系。

        2)装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强的功能,所以装饰类和被装饰的类通常都是属于一个体系。

        3)从继承结构转为组合结构。

注:在定义类的时候,不要以继承为主;可通过装饰设计模式进行增强类功能。灵活性较强,当装饰类中的功能不适合,可再使用被装饰类的功能。

示例:上面讲到的MyBufferedReader的例子就是最好的装饰设计模式的例子。

 

 
        流操作规律IO 字节流


一、概述

1、字节流和字符流的基本操作是相同的,但字节流还可以操作其他媒体文件。

2、由于媒体文件数据中都是以字节存储的,所以,字节流对象可直接对媒体文件的数据写入到文件中,而可以不用再进行刷流动作。

3、读写字节流:InputStream   输入流(读)

                             OutputStream  输出流(写)

4、为何不用进行刷流动作:

        因为字节流操作的是字节,即数据的最小单位,不需要像字符流一样要进行转换为字节。所以可直接将字节数据写入到指定文件中。

5InputStream特有方法:

        int available();//返回文件中的字节个数

注:可以利用此方法来指定读取方式中传入数组的长度,从而省去循环判断。但是如果文件较大,而虚拟机启动分配的默认内存一般为64M。当文件过大时,此数组长度所占内存空间就会溢出。所以,此方法慎用,当文件不大时,可以使用。

示例:

/*
练习:
复制一个图片
思路:
1、用字节读取流对象和图片关联。
2、用字节写入流对象创建一个图片文件。用于存储获取到的图片数据。
3、通过循环读写,完成数据的存储。
4、关闭资源。
*/
import java.io.*;
class  CopyPic
{
public static void main(String[] args) 
{
//常用方法复制
byteArrayCopy();
//利用输入流的available方法进行复制
availableCopy();
//利用available方法对复制文件大小有限制,慎用
}


//使用available方法进行复制
public static void availableCopy()
{
FileInputStream fis=null;
FileOutputStream fos=null;
try
{
//关联要复制的文件
fis=new FileInputStream("C:/Users/asus/Desktop/1.jpg");
//指定复制的路径
fos=new FileOutputStream("C:/Users/asus/Desktop/3.jpg");
//利用available方法指定数组长度
byte[] b=new byte[fis.available()];


fis.read(b);//复制关联文件数据


fos.write(b);//粘贴到指定路径


}
catch (IOException e)
{
throw new RuntimeException("图片复制失败");
}
finally
{
try
{
if(fis!=null)
fis.close();//关闭输入字节流
}
catch (IOException e)
{
throw new RuntimeException("读取字节流关闭失败");
}
try
{
if(fos!=null)
fos.close();//关闭输出字节流
}
catch (IOException e)
{
throw new RuntimeException("写入字节流关闭失败");
}
}
}
//使用读数组方式进行复制
public static void byteArrayCopy()
{
FileInputStream fis=null;
FileOutputStream fos=null;
try
{
//关联要复制的文件
fis=new FileInputStream("C:/Users/asus/Desktop/1.jpg");
//指定复制的路径
fos=new FileOutputStream("C:/Users/asus/Desktop/2.jpg");
//利用数组的读取方式
byte[] b=new byte[1024];
int len=0;
while ((len=fis.read(b))!=-1)//复制文件的全部数据
{
fos.write(b,0,len);//粘贴到指定路径
}
}
catch (IOException e)
{
throw new RuntimeException("图片复制失败");
}
finally
{
try
{
if(fis!=null)
fis.close();//关闭输入字节流
}
catch (IOException e)
{
throw new RuntimeException("读取字节流关闭失败");
}
try
{
if(fos!=null)
fos.close();//关闭输出字节流
}
catch (IOException e)
{
throw new RuntimeException("写入字节流关闭失败");
}
}
}
}
    

二、字节流缓冲区

        同样是提高了字节流的读写效率。

1、读写特点:

        read():会将字节byte型值提升为int型值

        write():会将int型强转为byte型,即保留二进制数的最后八位。

2、原理:将数据拷贝一部分,读取一部分,循环,直到数据全部读取完毕。

        1)先从数据中抓取固定数组长度的字节,存入定义的数组中,再通过然后再通过read()方法读取数组中的元素,存入缓冲区。

        2)循环这个动作,直到最后取出一组数据存入数组,可能数组并未填满,同样也取出包含的元素。

        3)每次取出的时候,都有一个指针在移动,取到数组结尾就自动回到数组头部,这样指针在自增。

        4)取出的时候,数组中的元素在减少,取出一个,就减少一个,直到减到0即元素取完。

        5)当文件中的全部数据都被读取出时,read()方法就返回-1

3、自定义读取字节流缓冲区

示例:

/*
自定义字节流读取缓冲区
思路:
1、定义一个固定长度的数组
2、定义一个指针和计数器用于读取数组长度,和计数数组元素是否取完为0
3、每次将字节数据存入元素要先将数组中的元素取完
 
*/
import java.io.*;
class MyBufferedInputStream
{
       privateInputStream in;
       privatebyte[] by=new byte[1024];
       privateint count=0,pos=0;
       MyBufferedInputStream(InputStreamin)
       {
              this.in=in;
       }


 
       //自定义读方法,一次读一个字节
       public int myRead()throws IOException
       {
              //通过in对象读取硬盘上数据,并存储by中。
              //存储在数组中的数据被读取完,再通过in对象从硬盘上读取数据
              if(count==0)
              {
                     count=in.read(by);
                     if(count<0)//文件数据全部被读取出来了
                            return-1;


 
                     pos=0;//初始化指针
                     byteb=by[pos];


                     count--;//每被读一个字节,表示数组中的字节数少一个
                     pos++;//指针加1
                     returnb&255;//返回的byte类型提升为int类型,字节数增加,且高24位被补1,原字节数据改变。
                                          //通过与上255,主动将byte类型提升为int类型,将高24位补0,原字节数据不变。
                                          //而在输出字节流写入数据时,只写该int类型数据的最低8位。
              }
              elseif(count>0)//如果数组中的数据没被读取完,则继续读取
              {
                     byteb=by[pos];
 
                     count--;
                     pos++;
                     returnb&0xff;
              }
              return-1;
       }
       
       //自定义关闭资源方法
       publicvoid close()throws IOException
       {
              in.close();
       }
}


 
//测试自定义输入字节流缓冲区
class MyBufferedCopyMp3
{
       publicstatic void main(String[] args) 
       {
              longstart=System.currentTimeMillis();
              //利用字节流的缓冲区进行复制
              copy_2();
              longend=System.currentTimeMillis();
              System.out.println("复制共用时:"+(end-start)+"毫秒");
       }
       //使用字节流的缓冲区进行复制
       publicstatic void copy_2()
       {
              BufferedOutputStreambout=null;
              MyBufferedInputStreambin=null;
              try
              {
                     //关联复制文件输入流对象到缓冲区
                     bin=newMyBufferedInputStream(new FileInputStream("C:/Users/asus/Desktop/一样的月光.mp3"));
                     //指定文件粘贴位置的输出流对象到缓冲区
                     bout=newBufferedOutputStream(new FileOutputStream("C:/Users/asus/Desktop/一样的月光2.mp3"));
                     intby=0;
 


                     while((by=bin.myRead())!=-1)
                     {
                            bout.write(by);//将缓冲区中的数据写入指定文件中
                     }
              }
              catch(IOException e)
              {
                     thrownew RuntimeException("MP3复制失败");
              }
              finally
              {
                     try
                     {
                            if(bin!=null)
                                   bin.close();//关闭输入字节流
                     }
                     catch(IOException e)
                     {
                            thrownew RuntimeException("读取字节流关闭失败");
                     }
                     try
                     {
                            if(bout!=null)
                                   bout.close();//关闭输出字节流
                     }
                     catch(IOException e)
                     {
                            thrownew RuntimeException("写入字节流关闭失败");
                     }
              }
       }
}




 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值