Java基础 IO流——第二部分

 

新博客地址:Temi

第一讲,IO流(BufferedWriter)

一,字符流的缓冲区概述:

  1. 缓冲区的出现提高了对数据的读写效率。
  2. 对应类:BufferedWriter,BuuferedReader。(存在于java.io包中)
  3. 缓冲区要结合流才可以使用。       ====缓冲区是为了提高流的操作效率出现的,所以在创建缓冲区之前必须要现有流对象====
  4. 在流的基础上对流的功能进行了增强。

                      ========缓冲技术原理:BufferedWriter,BufferedReader对象里面封装了数组==========

二,缓冲区操作类的简单了解:

                    BufferedWriter  类:

          1. 类的定义: public class BufferedWriter  extends Writer    将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
          2. 构造方法:public BufferedWriter (Writer out) 创建一个使用默认大小输出缓冲区的缓冲字符输出流。===注:此处必须指明Writer对象作为参数,原因见概述第三条==========
          3. 构造方法:public BufferedWriter(Writer out, int sz)    创建一个使用给定大小输出缓冲区的新缓冲字符输出流。
          4. 方法:public void newLine()  throws IOException     写入一个行分隔符。行分隔符字符串由系统属性 line.separator 定义,并且不一定是单个新行 (' ') 符。
          5. public void write(int c)  throws IOException    写入单个字符。===注:此方法被重载多次,可写入char数组和字符串====

                   BufferedReader 类:

          1. 类的定义:public class BufferedReader  extends Reader    从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
          2. 构造方法:public BufferedReader(Reader in)     创建一个使用默认大小输入缓冲区的缓冲字符输入流。==注:指明Reader对象==
          3. 构造方法:public BufferedReader(Reader in,int sz)   创建一个使用指定大小输入缓冲区的缓冲字符输入流。
          4. 方法: public int read() throws IOException   读取单个字符。返回值:作为一个整数(其范围从 0 到 65535 (0x00-0xffff))读入的字符,如果已到达流末尾,则返回 -1
          5. 方法: public int read(char[] cbuf, int off,  int len)  throws IOException    将字符读入数组的某一部分。==注: 包括off下标==
          6. 方法: public String readLine() throws IOException     读取一个文本行。通过下列字符之一即可认为某行已终止:换行 (' ')、回车 (' ') 或回车后直接跟着换行。
          7. 方法: public long skip(long n) throws IOException   跳过字符。返回值:实际跳过的字符数量。

三,缓冲区写入操作步骤:

  1. 创建一个字符写入流对象:    FileWriter fw=new FileWriter("buf.txt");
  2. 创建缓冲区对象:         BufferedWriter bw=new BufferedWriter(fw);
  3. 调用缓冲区对象方法写入数据:         bw.write("abcd");   ===注:此步骤执行后,文件若不存在会被创建,但是,数据并没有写入文件。=====
  4. 刷新缓冲区:                          bw.flush();                 ===注:用到缓冲区后一定要刷新===
  5. 关闭缓冲区:                          bw.close();                  ===注:缓冲区只是提高操作效率,真正实现写操作的是FileWriter对象,所以缓冲区的关闭其实是关闭的是他所提高效率的流对象,即FileWriter 对象。===

四,代码练习:

 1 /*
 2 * 缓冲区对象使用联系。重点观察写入过程
 3 *什么时候创建文件,以及将数据写入文件的时机
 4 */
 5 import java.io.*;
 6 import java.util.Scanner;
 7 
 8 
 9 public class BufferedWriterDemo {
10              public static void main(String args[]){
11                  
12                    //声明实际写文件对象引用
13                    FileWriter fw=null;
14                    
15                    //声明缓冲区对象引用
16                    BufferedWriter bw=null;
17                    
18                    //表示文件字符串
19                    String fileName="E:/buf.txt";
20                    
21                    //异常处理
22                    try{
23                        
24                        //实例化对象引用
25                        fw=new FileWriter(fileName);
26                        
27                        bw=new BufferedWriter(fw);
28                        
29                        
30                        //调用缓冲对象方法写入数据此时并没有写进文件中,但是文件已经创建。若文件存在由于不是追加写方式,源文件内容清空
31                        bw.write("abcd");
32                        
33                        //写入文件换行符,此方法跨平台
34                        bw.newLine();
35                        
36                        //写入第二行
37                        bw.write("第二行");
38                        
39                        //此处停顿,按任意键继续,此时可观察文件变化
40                        System.out.println("刷新流之前:");
41                        System.out.println("按任意键继续:");
42                        
43                        
44                        //用户输入任意字符后继续;
45                        new Scanner(System.in).next();
46                        
47                        //刷新缓冲流,将字符写入文件。
48                        bw.flush();
49                        
50                        //此后观察文件发现数据已经写入
51                        System.out.println("刷新流之后:");
52                        
53                         
54                    }catch(IOException e){
55                         System.out.println("写入操作发生错误!");
56                    }finally{
57                        try{
58                            if(bw!=null)
59                                bw.close();
60                        }catch(IOException e){
61                            System.out.println("关闭文件发生错误!");
62                        }
63                      
64                            
65                    }
66              }
67 }

第二讲:IO流(BufferedReader)

 一,BufferedReader类的了解:见第一讲

二,缓冲区读入步骤:

  1. 创建一个读取流对象和文件相关联。     FileReader fr=new FileReader("buf.txt");
  2. 创建缓冲读取对象,提高读取操作效率。BufferedReader br=new BufferedReader(fr);
  3. 使用缓冲区对象方法读取数据:            br.readLine();   ==注:readLine() 方法对于读取文本文件特别方便。特别注意:如果已到达流末尾,则返回 null 而不是 -1 ,此方法返回的字符串中不包括换行符==
  4. 关闭缓冲区。

三,代码练习:

 1 import java.io.*;
 2 
 3 
 4 public class BufferedReaderDemo {
 5 
 6     public static void main(String[] args) {
 7         // TODO Auto-generated method stub
 8            
 9            //创建对象引用
10            FileReader fr=null;
11            BufferedReader br=null;
12            
13            //文件字符串
14            String fileName="E:/buf.txt";
15            
16            
17            //异常处理
18            try{
19                fr=new FileReader(fileName);
20                
21                br=new BufferedReader(fr);
22                
23                //创建字符串,保存读取内容
24                String readLine=null;
25                
26                //循环读取文件内容,注意此处的判断条件是 null  而不是   -1
27                while((readLine=br.readLine())!=null){
28                    System.out.println(readLine);
29                }
30                
31                
32                //处理异常,给出提示
33            }catch(FileNotFoundException e){
34                System.out.println("文件没有找到!"+e.toString());
35            }catch(IOException e){
36                System.out.println("文件读取发生错误"+e.toString());
37            }finally{
38                try{
39                    if(br!=null)
40                        br.close();
41                }catch(IOException e){
42                    System.out.println("文件关闭失败:"+e.toString());
43                }
44            }
45     }
46 
47 }

第三讲:IO流(通过缓冲区复制文本文件)

一,练习:通过缓冲区复制一个 .java文件

             注意事项:

      1. readLine() 方法返回的字符串中不包括换行符,所以再写入新的文件时应该加上,使用BudderedWriter.newLine()方法。
      2. 每次循环写入都必须刷新

二,代码练习:

 1 import java.io.*;
 2 
 3 
 4 public class CopyFile {
 5              public static void main(String args[]){
 6                      
 7                      //创建对象引用
 8                      BufferedReader br=null;
 9                      
10                      BufferedWriter bw=null;
11                      
12 
13                     //源文件字符串表示
14                      String srcFileName="E:/test.java";
15                      
16 
17                      //目标文件字符串表示
18                      String destFileName="E:/dest.java";
19   
20                      //判断是否是.java文件
21                      if(!srcFileName.endsWith(".java")){
22                          System.out.println("文件后缀名不是 .java");
23                          
24                          //如果不是.java文件返回
25                          return;
26                      }
27                      
28 
29 
30                      //异常处理
31                      try{
32 
33 
34                          //使用匿名对象实例化缓冲区对象br 
35                          br=new BufferedReader(new FileReader(srcFileName));
36                          
37                          bw=new BufferedWriter(new FileWriter(destFileName));
38                          
39                          //接受读入的字符串
40                          String readLine=null;
41                          
42 
43                          //循环读取
44                          while((readLine=br.readLine())!=null){
45 
46                                  //读取一行,写入一行
47                              bw.write(readLine);
48 
49                                  //由于readLine() 方法没有返回换行符,此处应当换行
50                              bw.newLine();
51 
52                                  //刷新缓冲区,将数据写入文件
53                              bw.flush();
54                          }
55 
56                          //成功提示
57                          System.out.println("文件拷贝完毕!");
58 
59                       //异常处理以及提示
60                      }catch(FileNotFoundException e){
61                          System.out.println("源文件没有找到,或者目标文件不存在"+e.toString());
62                      }catch(IOException e){
63                          System.out.println("文件拷贝失败"+e.toString());
64                      }
65              }
66 }

 第四讲:IO流(readLine的原理图例)

原理概括,readLine 方法最终操作其实也是一个一个的读取数据,只不过它把读取到的数据存进了自己的缓冲区中,当遇到换行符时,结束读取,并一次性返回所有数据。如图:

 

第五讲:IO流(MyBufferedReader)

 自定义readLine方法代码:

  1 import java.io.*;
  2 
  3 class MyBufferedReader {
  4 
  5           //定义对象引用,并进行封装,使用构造函数实例化
  6       private FileReader reader;
  7       
  8 
  9          //定义缓冲区,缓冲读入的字符
 10       private char[] str;
 11       
 12      
 13           //构造方法,传入一个FileReader对象进行文件读操作,使用默认缓冲区
 14       public MyBufferedReader(FileReader reader){
 15           this.reader=reader;
 16           this.str=new char[1024];
 17       }
 18       
 19 
 20          //使用自定义的缓冲区大小
 21       public MyBufferedReader(Reader Filereader,int size){
 22           this.reader=reader;
 23           this.str=new char[size];
 24       }
 25       
 26       
 27 
 28           //自定义函数进行缓冲的高效读写。此处异常交由调用者处理。
 29       public String myReadLine() throws IOException{
 30                     
 31                      //保存读取的单个字符;
 32              int ch=0;
 33                      
 34                      //记录读取的总字符数量
 35              int num=0;
 36 
 37                      //循环读取内容
 38              while((ch=this.reader.read()) != -1){
 39                    
 40 
 41                            //如果字符为 '
' 则跳过继续下一轮循环
 42                    if(ch == '
')
 43                        continue;
 44 
 45                            //如果字符为 '
' 则结束循环,返回读取的内容
 46                    else if(ch == '
')
 47                        return new String(str,0,num);
 48 
 49                           //如果超出缓冲区大小,则结束循环,返回读取内容
 50                           else if(num>=size)
 51                        return new String(str,0,num);
 52                    else{
 53 
 54                                    //将读取的字符保存在字符数组中,下标加一
 55                        str[num]=(char)ch;
 56                        num++;
 57                    }
 58              }
 59 
 60                      //判断最后一行数据是否存在
 61              if(num!=0)
 62              return new String(str,0,num);
 63              else return null;
 64       }
 65       
 66       
 67           //关闭流,实为关闭内部流对象。此处异常抛出。
 68       public void myClose() throws IOException{
 69           this.reader.close();
 70       }
 71 }
 72 
 73 
 74 
 75 public class MyBufferedReaderDemo {
 76 
 77     public static void main(String[] args) {
 78         // TODO Auto-generated method stub
 79         MyBufferedReader mbr=null;
 80         
 81         String fileName="E:/testmybuf.txt";
 82         
 83         try{
 84             mbr=new MyBufferedReader(new FileReader(fileName));
 85             
 86             String readLine;
 87 
 88                //循环读取
 89             while((readLine=mbr.myReadLine())!=null){
 90                 System.out.println(readLine);
 91             }
 92             System.out.println("读取完毕!");
 93             
 94         }catch(IOException e){
 95             System.out.println("读取文件错误"+e.toString());
 96         }finally{
 97             try{
 98                 if(mbr!=null){
 99                     mbr.myClose();
100                 }
101             }catch(IOException e){
102                 System.out.println("文件关闭时发生错误!"+e.toString());
103             }
104         }
105     }
106 
107 }

第六讲、第七讲、第八讲:装饰设计模式、装饰和继承的区别、自定义装饰类

一,装饰设计模式简介:

    1.  装饰模式(Decorator)的定义:当想对已有对象进行功能增强时,可定义一个类,这个类将已有对象传入,基于已有对象的功能,并提供加强功能,那么自定义的该类称之为装饰类。又名包装(Wrapper)模式,装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。
    2. 装饰模式的特点:
        1. 装饰类通常都会通过构造方法接收被装饰的对象,并基于被装饰的对象的功能,提供更强的功能。
        2. 装饰对象包含一个真实对象的引用(reference).
        3. 通常装饰类,与被装饰类实现同一个接口。即属于同一个接口或者类。
    1. 装饰设计模式和继承的区别:
        1. 装饰模式比继承要灵活。避免了继承体系的臃肿,且降低了类与类之间的关系。装饰模式扩展的是对象的功能,不需要增加类的数量,而类继承扩展是类的功能,在继承的关系中,如果我们想增加一个对象的功能,我们只能通过继承关系,在子类中增加两个方法。
        2. 装饰模式是一种动态行为,可以对已经存在类进行随意组合,而类的继承是一种静态的行为,一个类定义成什么样的,该类的对象便具有什么样的功能,无法动态的改变。

 

 

二,代码练习(第五讲代码增强):

 

  1 import java.io.*;
  2 
  3 class MyBufferedReader {
  4 
  5           //定义对象引用,并进行封装,使用构造函数实例化
  6       private FileReader reader;
  7       
  8 
  9          //定义缓冲区,缓冲读入的字符
 10       private char[] str;
 11       
 12      
 13           //构造方法,传入一个FileReader对象进行文件读操作,使用默认缓冲区
 14       public MyBufferedReader(FileReader reader){
 15           this.reader=reader;
 16           this.str=new char[1024];
 17       }
 18       
 19 
 20          //使用自定义的缓冲区大小
 21       public MyBufferedReader(Reader Filereader,int size){
 22           this.reader=reader;
 23           this.str=new char[size];
 24       }
 25       
 26       
 27 
 28           //自定义函数进行缓冲的高效读写。此处异常交由调用者处理。
 29       public String myReadLine() throws IOException{
 30                     
 31                      //保存读取的单个字符;
 32              int ch=0;
 33                      
 34                      //记录读取的总字符数量
 35              int num=0;
 36 
 37                      //循环读取内容
 38              while((ch=this.reader.read()) != -1){
 39                    
 40 
 41                            //如果字符为 '
' 则跳过继续下一轮循环
 42                    if(ch == '
')
 43                        continue;
 44 
 45                            //如果字符为 '
' 则结束循环,返回读取的内容
 46                    else if(ch == '
')
 47                        return new String(str,0,num);
 48 
 49                           //如果超出缓冲区大小,则结束循环,返回读取内容
 50                           else if(num>=size)
 51                        return new String(str,0,num);
 52                    else{
 53 
 54                                    //将读取的字符保存在字符数组中,下标加一
 55                        str[num]=(char)ch;
 56                        num++;
 57                    }
 58              }
 59 
 60                      //判断最后一行数据是否存在
 61              if(num!=0)
 62              return new String(str,0,num);
 63              else return null;
 64       }
 65       
 66       
 67           //关闭流,实为关闭内部流对象。此处异常抛出。
 68       public void myClose() throws IOException{
 69           this.reader.close();
 70       }
 71 
 72 
 73 
 74        //覆写父类中的抽象方法
 75         @Override
 76     public int read(char[] cbuf, int off, int len) throws IOException {
 77 
 78                 //调用真是实现类实现具体操作
 79         return this.reader.read(cbuf, off, len);
 80     }
 81 
 82 
 83          //覆写父类中的抽象方法
 84     @Override
 85     public void close() throws IOException {
 86         this.reader.close();
 87         
 88     }
 89 }
 90 
 91 
 92 
 93 public class MyBufferedReaderDemo {
 94 
 95     public static void main(String[] args) {
 96         // TODO Auto-generated method stub
 97         MyBufferedReader mbr=null;
 98         
 99         String fileName="E:/testmybuf.txt";
100         
101         try{
102             mbr=new MyBufferedReader(new FileReader(fileName));
103             
104             String readLine;
105 
106                //循环读取
107             while((readLine=mbr.myReadLine())!=null){
108                 System.out.println(readLine);
109             }
110             System.out.println("读取完毕!");
111             
112         }catch(IOException e){
113             System.out.println("读取文件错误"+e.toString());
114         }finally{
115             try{
116                 if(mbr!=null){
117                     mbr.myClose();
118                 }
119             }catch(IOException e){
120                 System.out.println("文件关闭时发生错误!"+e.toString());
121             }
122         }
123     }
124 
125 }

第九讲、第十讲:IO流(LineNumberReader)、IO流(MyineNumberReader)

一,LineNumberReader类的了解:

      1. 类的定义:public class LineNumberReader  extends BufferedReader     跟踪行号的缓冲字符输入流。此类定义了方法 setLineNumber(int)
        getLineNumber(),它们可分别用于设置和获取当前行号。==注:默认情况下,行编号从 0 开始。该行号随数据读取在每个行结束符处递增,可以通过调用 setLineNumber(int) 更改行号。setLineNumber(int) 不会实际更改流中的当前位置;它只更改将由 getLineNumber() 返回的值。===
      2. 方法:public int getLineNumber()     获得当前行号。
      3. 方法:public void setLineNumber(int lineNumber)    设置当前行号。

二,LineNumberReader类的原理:

                         在类的内部增加了一个行号计数器。

三,代码练习:

 1 import java.io.*;
 2 class  LineNumberReaderDemo
 3 {
 4     public static void main(String[] args) 
 5     {
 6         LineNumberReader lnr=null;
 7         try
 8         {
 9              
10             lnr=new LineNumberReader(new FileReader("LineNumberReaderDemo.java"));
11 
12                         //设置行号:此设置仅对 getLineNumber() 有效并不会影响源文件
13             lnr.setLineNumber(100); 
14 
15                         //接受读取的字符串
16             String line=null;
17 
18                         //循环读取
19             while ((line=lnr.readLine())!=null ){
20                                 
21                                 //输出行号与内容
22                 System.out.println(lnr.getLineNumber()+":"+line); 
23             }
24         }
25 
26                 //异常处理
27         catch (IOException e)
28         {
29             throw new RuntimeException("读取数据失败");
30         }
31         finally
32         {
33             try
34             {
35                 if(lnr!=null)
36                     lnr.close();
37             }
38             catch (IOException e)
39             {
40                 throw new RuntimeException("读取流关闭失败");
41             }
42         }    
43     }
44 }

第十一讲,十二讲:IO流(字节流File读写操作)、IO流(拷贝图片)

一,字节流概述:

    1. 字节流除了可以操作文本文件外还可以操作其他文件,例如媒体文件。
    2. 字节流的顶层类: InputStream,OutputStream。
    3. 字节流的写入是直接写入文件的,所以不用进行刷新。==注:因为字节流操作的是字节,即数据的最小单位,不需要像字符流一样要进行转换为字节。所以可直接将字节数据写入到指定文件中。==

二,InputStream类的了解:

      1. 构造方法:public abstract class InputStream  extends Object  implements Closeable   此抽象类是表示字节输入流的所有类的超类。
      2. 独特的方法:public int available() throws IOException   返回可以不受阻塞地从此输入流读取(或跳过)的估计字节数;如果到达输入流末尾,则返回 0。===注:可以利用此方法来指定读取方式中传入数组的长度,从而省去循环判断。但是如果文件较大,而虚拟机启动分配的默认内存一般为64M。当文件过大时,此数组长度所占内存空间就会溢出。所以,此方法慎用,当文件不大时,可以使用。===
      3. 直接已知子类:AudioInputStream, ByteArrayInputStream, FileInputStream, FilterInputStream, InputStream, ObjectInputStream, PipedInputStream, SequenceInputStream, StringBufferInputStream

三,拷贝图片步骤:

      1. 用字节读取流对象和图片关联。
      2. 用字节流对象创建一个图片文件,存储获取到的图片数据。
      3. 通过循环读写,完成数据的存储。===注:此处不存在流的刷新====
      4. 关闭资源。

四,代码练习,拷贝图片:

        

 1 import java.io.*;
 2 public class  CopyImage{
 3     public static void main(String[] args){
 4 
 5                 //创建对象引用
 6         FileInputStream fis=null;
 7         FileOutputStream fos=null;
 8 
 9 
10         try{
11             //实例化对象,与文件相关联
12             fis=new FileInputStream("E:/image/pub.jpg");
13              
14             fos=new FileOutputStream("E:/image/pub2.jpg");
15 
16 
17             //创建数组用于保存读取到的数据                                                           byte[] b=new byte[1024];
18 
19                         //记录读取到的字节数
20             int len=0;
21 
22                         
23                         //循环读取
24             while ((len=fis.read(b))!=-1){
25                                 
26                                 //边读边写实现复制
27                 fos.write(b,0,len);
28             }
29         }
30 
31 
32         catch (IOException e)
33         {
34             throw new RuntimeException("图片复制失败");
35         }
36         finally
37         {
38             try
39             {
40                 if(fis!=null)
41                     fis.close();//关闭输入字节流
42             }
43             catch (IOException e)
44             {
45                 throw new RuntimeException("读取字节流关闭失败");
46             }
47             try
48             {
49                 if(fos!=null)
50                     fos.close();//关闭输出字节流
51             }
52             catch (IOException e)
53             {
54                 throw new RuntimeException("写入字节流关闭失败");
55             }
56         }
57     }    
58 }

第一十三讲、一十四讲:IO流(字节流的缓冲区)、IO流(自定义字节流的缓冲区-read和write的特点)

 一,缓冲输出流的了解:

      1. 用到的类BufferedOutputStream,BufferedInputStream.
      2. BufferedInputStream类的定义:public class BufferedInputStreamextends FilterInputStream 为另一个输入流添加一些功能,即缓冲输入以及支持 markreset 方法的能力。
      3. 方法与InputStream类相同。

二,缓冲区的原理:将数据拷贝一部分,读取一部分,循环,直到数据全部读取完毕。如图:

三,字节流操作注意事项:

      1. 读取方法应当返回 int 类型,而不是 byte 类型。==原理:数据在内存中以二进制形式存在,当读到八个一时,转换为 byte类型是 -1 ,则此时使用 -1作为文件结束的判断逻辑将会出错。解决办法:将byte 类型转换为 int 类型,并将转后的的数据的前24位二进制用零填充。代码实现: return byte&0xff;     0xff即 255 二进制形式为 00000000  000000000  00000000  11111111   所以将byte的前24位变为零==

四,代码练习:

  1 import java.io.*;
  2 
  3 
  4 public class MyBufferedInputStream {
  5              
  6     
  7              //定义被包装的类成员
  8              private InputStream in;
  9              
 10              //定义缓冲区的大小 
 11              private int size=1024;
 12              
 13              
 14              //定义变量分别表示读取数量,以及当前数组下标
 15              private int pos=0,count=0;
 16              
 17              //声明已知长度的缓冲区
 18              byte[] buf=new byte[size];
 19              
 20              
 21              //定义构造方法
 22              public MyBufferedInputStream(InputStream in){
 23                  this.in=in;
 24              }
 25              
 26             
 27              //定义构造方法
 28              public MyBufferedInputStream(InputStream in,int size){
 29                  this.in=in;
 30                  this.size=size;
 31              }
 32              
 33              
 34              //声明对外提供的方法
 35              //功能:一次从缓冲区中读取一个字节数据。
 36              public int myRead() throws IOException{
 37                  
 38                  //缓冲区中没有数据
 39                   if(count==0){
 40                       
 41                       //将数据读入缓冲区
 42                       count=in.read(buf);
 43                       
 44                       //到达文件末尾返回 -1
 45                       if(count<=0){
 46                           return -1;
 47                       }
 48                       
 49                       //返回缓冲区中的第一个字节
 50                       byte read=buf[pos];
 51                       
 52                       //缓冲区数据量 减一
 53                       count--;
 54                       
 55                       //缓冲区下标加一
 56                       pos++;
 57                       
 58                       //返回整形数据,原数据与上255,将钱24位设定为零,避免读取的字节为八个一时,错误判断为文件结束
 59                       return read&0xff;
 60                       
 61                   }
 62                   else {
 63                       
 64                       //缓冲区中有数据,直接返回
 65                       byte read=buf[pos];
 66                       
 67                       //改变下标
 68                       count--;
 69                       pos++;
 70                       
 71                       //返回修改之后的值
 72                       return read&0xff;
 73                   }
 74              }
 75              
 76              
 77              //定义主方法拷贝mp3
 78              public static void main(String args[]){
 79                  
 80                  
 81                  //声明引用句柄
 82                     FileInputStream src=null;
 83                     FileOutputStream dest=null;
 84                     MyBufferedInputStream mbi=null;
 85                     
 86                     //异常处理
 87                     try{
 88                         
 89                         //实例化源文件,目标文件
 90                         src=new FileInputStream("E:/my.mp3");
 91                         dest=new FileOutputStream("E:/my2.mp3");
 92                         
 93                         //实例化缓冲区读取对象
 94                         mbi=new MyBufferedInputStream(src);
 95                         
 96                         
 97                         //接受读取的数据
 98                         int read=0;
 99                         
100                         //循环读取数据并写入文件
101                         while((read=mbi.myRead())!=-1){
102                             dest.write(read);
103                         }
104                         
105                         
106                         //异常处理
107                     }catch(IOException e){
108                         System.out.println("文件复制错误"+e.toString());
109                     }finally{
110                         try{
111                             if(src!=null){
112                                 src.close();
113                             }
114                             if(dest!=null){
115                                 dest.close();
116                             }
117                         }catch(IOException e){
118                             System.out.println("文件关闭发生错误"+e.toString());
119                         }
120                     }
121              }
122 }

 

 

第一十五讲:IO流(读取键盘录入)

一,使用到的对象:System.in

      1. 该对象的定义:public static final InputStream in   “标准”输入流。此流已打开并准备提供输入数据。通常,此流对应于键盘输入或者由主机环境或用户指定的另一个输入源。======注:次对象使用完毕后可以不进行显示的关闭==========
      2. System的另一个静态对象:  public static final PrintStream out    “标准”输出流。此流已打开并准备接受输出数据。

二,需求分析:

                   通过键盘录入数据,当录入一行数据后,就将改行打印,如果录入的数据是 end ,那么停止录入。

三,代码实现:

 1 import java.io.*;
 2 
 3 
 4 public class ReadIn {
 5 
 6     public static void main(String[] args)  {
 7         // TODO Auto-generated method stub
 8         
 9         //创建输入对象,指向System.in  ======次对象可以不用显示关闭==========
10         InputStream in=System.in;
11         
12         //缓冲读入的字符
13         StringBuilder sb=new StringBuilder();
14         
15         
16         //一直读取键盘输入,直到用户输入end字符串
17         while(true){
18             
19             //接受输入字符
20             int ch=0;
21             
22             
23             //读取输入内容
24              try {
25                   ch=in.read();
26             } catch (IOException e) {
27                  System.out.println("读取发生错误"+e.toString());
28             }
29              
30              //进行判断,如果是  '
' 则进行下一次读取
31              if(ch==13)
32                  continue;
33              
34              //如果是 '
' 字符结束读取,打印用户的输入
35              else if(ch==10){
36                  
37                  //如果用户输入的是  "end" 字符串,则结束读取
38                  if("end".equals(sb.toString()))
39                      break;
40                  
41                  //否则打印用户输入,进行下一次读取
42                  System.out.println(sb);
43                  
44                  //打印完毕必须清空缓冲区
45                  sb.delete(0, sb.length());
46              }else 
47                  
48                  //普通字符存入缓冲区中
49              sb.append((char)ch);
50              
51         }
52     }
53 
54 }

               ===========键盘录入也可以使用 crtl + c 快捷键结束===============

第一十六讲,一十七讲:IO流(读取转换流),IO流(写入转换流)

一,需求分析:

                  使用readLine()方法读取键盘的一行数据。

                  使用newLine() 方法进行换行。

二,思路分析:

    1. readLine() 方法是字符流BufferedReader类中的方法。
    2. 负责接收键盘录入的read() 方法是字节流InputStream 类中的方法。
    3. newLine() 方法是字符流BufferedWriter 类中的方法。

三,解决办法:

    1. 使用转换流。InputStreamReader(字节转换字符流),OutputStreamReader(字符流转换字节流)。
      1. InputStreamReader 类的定义:public class InputStreamReaderextends Reader
      2. InputStreamReader 类的构造方法:
        1. public InputStreamReader(InputStream in)    创建一个使用默认字符集的 InputStreamReader。
        2. public InputStreamReader(InputStream in, String charsetName) throws UnsupportedEncodingException  创建使用指定字符集的 InputStreamReader。
        3. public InputStreamReader(InputStream in, Charset cs)     创建使用给定字符集的 InputStreamReader。
      3. OutputStreamWriter 类的定义:public class OutputStreamWriterextends Writer   OutputStreamWriter 是字符流通向字节流的桥梁
      4. OutputStreamWriter 类的构造方法:
        1. public OutputStreamWriter(OutputStream out)     创建使用默认字符编码的 OutputStreamWriter。
        2. public OutputStreamWriter(OutputStream out,  Charset cs)      创建使用给定字符集的 OutputStreamWriter。
        3. public OutputStreamWriter(OutputStream out,  CharsetEncoder enc)     创建使用给定字符集编码器的 OutputStreamWriter。
    2. 将字节流转换成字符流,之后再使用字符流的 readLine() ,newLine()方法进行数据的按行读取,以及进行换行操作。

四,练习代码:

 

 1 import java.io.*;
 2 
 3 
 4 public class TransStreamDemo {
 5              public static void main(String args[]){
 6                  
 7                  //创建字符流对象,此对象包装了字节流对象
 8                  InputStreamReader isr=new InputStreamReader(System.in);
 9                  
10                  
11                  //创建缓冲字符流对象,使用readLine() 方法
12                  BufferedReader br=new BufferedReader(isr);
13                  
14                  //接受输入的字符串
15                  String line=null;
16                  
17                  //循环读取用户输入内容
18                  while(true){
19                      try {
20                          
21                          //如果用户输入 "end" 则结束读取
22                         if("end".equals(line=br.readLine()))
23                              break;
24                     } catch (IOException e) {
25                         // TODO Auto-generated catch block
26                         System.out.println("读取发生错误"+e.toString());
27                     }
28                      
29                      //输出用户的输入
30                      System.out.println(line);
31                  }
32                  
33              }
34 }

 ===============键盘录入最常见写法:BufferedReaderin=new BufferedReader(new InputStreamReader(System.in));====================

第一十八讲:IO流(流操作规律-1)

 一,操作流程:

    1. 明确目的和源:
      1. 源:键盘录入。
      2. 目的:控制台(屏幕设备)。
    2. 需求分析:
      1. 把键盘录入的数据存储到一个文件中。======源:键盘,目的地:文件(硬盘)==========
      2. 把一个文件数据打印到控制台上。      ======源:文件,目的地:控制台==========
    3. 通过两个明确来选择众多流对象中具体应该用那中体系。--------1,明确目的和源。2,操作的文件或者是源,是否是文本形式的。-----------------
    4. 当体系明确后再明确具体使用那个对象。        ====源设备:内存,硬盘,键盘,目的:内存,硬盘,控制台=====

二,练习分析:

    1. 将一个文本文件数据,存储到另一个文本文件中,即复制文件。
      1. 源:应为是源所以使用读取流(InputStream, Reader)。
      2. 是不是文本文件  (Reader)。  ===明确体系===
      3. 确定源对象:因为设备是硬盘文件,选择FileReader。      FileReader  fr=new FileReader("源.txt");
      4. 目的:因为是目的所以使用写入流(OutpurStream, Writer)。
      5. 是不是文本文件  (Writer)。   
      6. 确定目的对象:FileWriter。                                       FileWriter fw=new FileWriter("目的.txt");
      7. 输入流提高效率:  加入BufferedReader                       BufferedReader br=new BufferedReader(fr);
      8. 输出流提高效率:  加入BufferedWriter                        BufferedWriter bw=new BufferedWriter(fw);

三,复制图片代码练习:

 

 1 import java.io.*;
 2 
 3 
 4 public class MyImage {
 5              public static void main(String args[]){
 6                   
 7                  //确定使用的对象===源:硬盘,图片文件,目的:硬盘,图片文件
 8                  FileInputStream fis=null;
 9                  FileOutputStream fos=null;
10                  
11                  
12                  //使用缓冲流提高效率
13                  BufferedInputStream bis=null;
14                  BufferedOutputStream bos=null;
15                  
16                  
17                  String src="F:/Image/psb.jpg";
18                  String dest="F:/Image/psb2.jpg";
19                  
20                  try{
21                      
22                      //实例化对象
23                       fis=new FileInputStream(src);
24                       bis=new BufferedInputStream(fis);
25                       
26                       bos=new BufferedOutputStream(fos=new FileOutputStream(dest));
27                       
28                       //转存读入的内容
29                       byte[] b=new byte[1024];
30                       
31                       //循环读取写入实现文件复制
32                       while(bis.read(b)!=-1)
33                           bos.write(b);
34                       
35                       //给出成功提示
36                       System.out.println("文件复制成功");
37                  }catch(IOException e){
38                      System.out.println("文件复制错误!"+e.toString());
39                  }finally{
40                      try{
41                          if(bis!=null)
42                              bis.close();
43                          if(bos!=null)
44                              bos.close();
45                      }catch(IOException e){
46                          System.out.println("文件关闭过程发生错误!"+e.toString());
47                      }
48                  }
49              }
50 }

第一十九讲:IO流(流操作规律-2)

一,扩展:把录入的数据按照指定的编码表(UTF-8)(默认编码表是GBK),将数据存到文件中。

    1. 想要实现使用指定的编码表将数据存入文件中,只能使用转换流。OutputStreamWriter osw=new OutputStreamWriter(new FileInputStream("d.txt"),"UTF-8");
    2. 提高效率:BufferedWriter bw=new BufferedWriter(osw);

====转换流的使用时机:1,字符和字节之间的桥梁。2,涉及到字符编码转换。===

二,代码练习:使用指定的编码表(UTF-8)将键盘输入的数据存入文件中

 

 1 import java.io.*;
 2 
 3 public class TransStreamDemo2 {
 4              public static void main(String args[]){
 5                  
 6                  
 7                  //确定输入源为键盘,创建相对应的输入流对象,并使用装饰流提高效率
 8                  InputStream in=System.in;
 9                  
10                  //输入流输入的为文本文件,使用转换流进行转换
11                  InputStreamReader isr=new InputStreamReader(in);
12                  BufferedReader br=new BufferedReader(isr);
13                  
14                  //读取键盘输入的常用格式:
15                  //以上三句话可以省略写为:BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
16                  //确定输出源为文件,创建相对应输出流对象,并使用装饰流提高效率
17                  FileOutputStream fos=null;
18                  
19                  //输出流输出的为文本文件,使用输出流进行转换
20                  OutputStreamWriter isw=null;
21                  BufferedWriter bw=null;
22                  try{
23                      
24                      //创建输出缓冲流,其中转换里流明确使用UTF-8编码格式
25                      bw=new BufferedWriter(isw=new OutputStreamWriter(fos=new FileOutputStream("E:/test.txt"),"UTF-8"));
26                      
27                      //接受读入的一行数据
28                      String line=null;
29                      
30                      //循环读取写入
31                      while(!"end".equals(line=br.readLine())){
32                          
33                          //写入文件
34                          bw.write(line);
35                          
36                          //写入换行符
37                          bw.newLine();
38                          
39                          //缓冲流需要刷新
40                          bw.flush();
41                      }
42                      
43                      //成功提示
44                      System.out.println("存入完毕");
45                      
46                      //异常处理
47                  }catch(IOException e){
48                      System.out.println("发生错误!"+e.toString());
49                  }finally{
50                      try{
51                          if(bw!=null)
52                              bw.close();
53                      }catch(IOException e){
54                          System.out.println("文件关闭发生错误!"+e.toString());
55                      }
56                  }
57              }
58 }

 

第二十讲:IO流(改变标准输入输出设备)

一,改变标准输入、输出设备用到的System类中的方法:

      1. public static void setIn (InputStream in)  重新分配“标准”输入流。
      2. public static void setOut(PrintStream out)   重新分配“标准”输出流。

二,代码练习:通过改变标准输入、输出实现文件的复制

 1 import java.io.*;
 2 
 3 
 4 public class TransStreamDemo3 {
 5              public static void main(String args[]){
 6                  
 7                  //目的和源都是 文件,创建相对应的流对象引用
 8                  FileInputStream in=null;
 9                  PrintStream out=null;
10                  
11                  //确定操作的是文本文件,使用相对应的缓冲刘提高效率
12                  BufferedWriter bw=null;
13                  BufferedReader br=null;
14                  
15                  //异常处理
16                  try{
17                      
18                      //实例化输入输出流对象
19                      in=new FileInputStream("E:/test.txt");
20                      out=new PrintStream("E:/test_copy.txt");
21                      
22                      //分别调用 setIn() setOut() 方法重定向标准输入、输出。
23                      System.setIn(in);
24                      System.setOut(out);
25                      
26                      
27                      //实例化缓冲流。使用转换流进行转换
28                      br=new BufferedReader(new InputStreamReader(System.in));
29                      bw=new BufferedWriter(new OutputStreamWriter(System.out));
30                      
31                      //接受读入的一行数据
32                      String line=null;
33                      
34                      //循环读入写入操作
35                      while((line=br.readLine())!=null){
36                          
37                          //写入数据
38                          bw.write(line);
39                          
40                          //换行操作
41                          bw.newLine();
42                          
43                          //清空缓冲区
44                          bw.flush();
45                      }
46                      
47                      //操作成功给出提示
48                      System.out.println("文件复制成功!");
49                  }catch(FileNotFoundException e){
50                      System.out.println("文件没有找到"+e.toString());
51                  }catch(IOException e){
52                      System.out.println("文件复制发生作物"+e.toString());
53                  }finally{
54                      try{
55                          if(br!=null)
56                              br.close();
57                          if(bw!=null)
58                              bw.close();
59                      }catch(IOException e){
60                          System.out.println("文件关闭发生错误"+e.toString());
61                      }
62                  }
63              }
64 }

 

第二十一讲,二十二讲:IO流(异常的日志信息),IO流(系统信息)

一,需求分析:

    1. 将程序运行时异常记录在文件中。
    2. 加入异常产生的时间。

二,思路:

    1. 获取文件输出流,输出异常信息。
    2. 记录异常产生时间,并输入文件。
    3. 获取异常信息,并将之输入文件。

三,代码实现:

 1 import java.io.*;
 2 import java.util.Date;
 3 import java.text.SimpleDateFormat;
 4 
 5 
 6 public class ExceptionInfo {
 7              public static void main(String arga[]){
 8                  
 9                           //测试记录函数,此处会发生ArrayIndexOutOfBoundsException
10                            try{
11                                String s[]=new String[2];
12                                s[3]="li";
13                            }catch(Exception e){
14                                log(new Date(),e);
15                            }
16              }
17              
18              //声明将异常记录在文件方法
19              public static void log(Date date,Exception e){
20                  //记录异常文件名
21                  String filename="E:/Exception.log";
22                  
23                  //声明缓冲输出流,提高操作效率
24                  BufferedWriter bw=null;
25                  try{
26                      
27                      //实例化输出对象
28                      bw=new BufferedWriter(new FileWriter(filename));
29                      
30                      //声明格式化日期操作类,格式化日期格式
31                      SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
32                      
33                      //写入异常发生时间
34                      bw.write(sdf.format(date)+"===");
35                      
36                      //写入异常信息
37                      bw.write(e.toString());
38                  }catch(IOException ex){
39                      System.out.println("记录异常发生错误"+ex.toString());
40                  }finally{
41                      try{
42                          if(bw!=null)
43                              bw.close();
44                      }catch(Exception ex){
45                          System.out.println("关闭文件发生错误"+ex.toString());
46                      }
47                  }
48              }
49 }

四,输出系统信息。

    1. 获取系统信息:             Propertes  prop=System.getProperties();
    2. 列出系统信息:             prop.list(new PrintStream("E:/sysinfo.txt");

五,代码练习:

 1 import java.io.*;
 2 import java.util.Properties;
 3 
 4 
 5 public class SysInfo {
 6              public static void main(String args[]){
 7                  
 8                  //获取系统信息
 9                  Properties prop=System.getProperties();
10                  
11                  //声明输出流句柄
12                  PrintStream ps=null;
13                  try{
14                      
15                      //实例化对象
16                      ps=new PrintStream("E:/sysinfo.txt");
17                      
18                      //将系统信息输出到指定流中
19                      prop.list(ps);
20                  }catch(IOException e){
21                      System.out.println("写入错误"+e.toString());
22                  }finally{
23                      try{
24                          if(ps!=null)
25                              ps.close();
26                      }catch(Exception e){
27                          System.out.println("关闭文件错误!"+e.toString());
28                      }
29                  }
30              }
31 }

六,常用到的系统信息:

    1. user.language=zh   用户的语言
    2. file.encoding=GBK  系统编码
    3. user.name=Thinkpad  用户名
    4. line.separator=          换行符
    5. os.name=Windows 8  操作系统
    6. path.separator=;       路径分割符
 
原文地址:https://www.cnblogs.com/xiaochongbojue/p/4045554.html