day18(下)IO流1(FileWriter,FileReader)

 

1.IO概述:

/*
 IO流概述:
 1.IO流用来处理设备之间的数据传输
 2.java对数据的操作时通过流的方式
 3.java用于操作流的对象都在IO包中
 4.流按操作数据分为两种:字节流和字符流
   简单来说:
   字符流:在内部融合了编码表(UTF-8,GBK....)
          文字,字符等涉及到编码.
   通用为字节流,字符流基于字节流
 
 5.流按流向分为:输入流,输出流
*/

2.FileWriter类:

/*
字符流和字节流
 字节流两个基类:
 InputStream  OutputStream
 
 字符流两个基类:
 Reader  writer
  
 既然IO流是用于操作数据的
 那么数据的最常见体现形式为:文件(存储数据)

 
 找到一个专门用于操作文件的Writer子类对象
 FileWriter,后缀名为父类名,前缀名是该流对象功能
 
 FileWriter中为什么没有空参数构造函数?
   需要向文件中写入数据,流对象一经初始化需要有操作的文件存在.
*/
//需求:在硬盘上,创建一个文件并写入一些文字数据
package filewriter;
import java.io.FileWriter;
import java.io.IOException;
class FileWriterDemo{
 public static void main(String[] args)throws IOException{
 
  //创建一个FileWriter对象,该对象一经初始化必须要明确被操作的文件
  //而且文件会被创建到指定目录下(不写路径默认当前目录)
  //如果该目录下已有同名文件,将被覆盖
  FileWriter fw= new FileWriter("FileWriter.txt");//该构造函数会抛出IOException
                                                  //该部就是在明确数据要存放的目的地.
                                                  
 

  fw.write("hello");//写入字符串:并没有写入目的地,而是写到内存(流)中 
  
  fw.flush();
  /*
  刷新该流的缓冲。
  如果该流已保存缓冲区中各种 write() 方法的所有字符,
  则立即将它们写入预期目标。
 */
  fw.write("java");
  fw.flush();
  
  
  fw.close();
  /*
  关闭此流,但要先刷新它.
  
  在关闭该流之后,
  再调用 write() 或 flush() 将导致抛出 IOException。 
  
  对比flush():
    flush刷新后,流依然可以使用.而close刷新后,会将关闭流
  */
  
  }

}
/*
关于IOException
 如果指定文件存在,但它是一个目录,
 而不是一个常规文件;或者该文件不存在,但无法创建它;
 抑或因为其他某些原因而无法打开它

以上write,flush,close方法均可能发生I/O错误->产生IOException
->函数上均有异常声明->必须try..catch/throws
*/

/*
关于close():
 其实java在调用所在平台(windows,linux...)
 的各种功能来完成文件的创建,写入...
 所做的调用均是在使用OS的资源,因此在使用后释放(close)该资源.
*/

3.※IO异常处理:

/*
IOException处理
*/
package filewriter;
import java.io.FileWriter;
import java.io.IOException;
class FileWriterDemo2{
    public static void main(String[] args){
    
        FileWriter fw=null;
        try{
         fw= new FileWriter("k:\\test.txt");
         fw.write("haha");
         fw.flush();
        }
        catch(IOException e){
         System.out.println("catch "+e.toString());
        } 
        
        finally{
         try{
          if(fw!=null)
            fw.close();
         }
         catch(IOException e){
           System.out.println(e.toString());
         }
        }
        System.out.println("over");
        return;
  }
}
/*
分析以上写法:
①.write,flush,close均会发出异常,为什么不用3个try..catch处理??
   这是因为一旦 初始化时发生异常/write发生异常 下面操作(flush,close)将
   无任何意义,也就是不再执行.
  try{
  FileWriter fw = new FileWriter("test.txt");
  fw.write("abcd");
  fw.flush();
  fw.close();
  }
  catch(IOException e){
  
  }
②如果初始化成功(创建文件成功),在write过程中发生IOException(例如:不断写导致硬盘空间不足)
  那么fw.close()将不再执行,也就是说流资源无法关闭.(这点类似数据库操作异常导致数据库与用户连接不能断开)
  鉴于此,把fw.close放在finally中(finally经常用于关闭资源),不论是否发生异常,都在退出方法前执行fw.close()
  放到finally中的close依然需要try...catch
    try{
      FileWriter fw = new FileWriter("test.txt");
      fw.write("abcd");
      fw.flush();
  
    }
  catch(IOException e){
   
  }
  finally{
         try{
         fw.close();
         }
         catch(IOException e){
           System.out.println(e.toString());
         }
    }
  
  ->fw的作用域仅仅在try中->因此在try外声明,try内初始化
   FileWriter fw =null;
   try{
      fw = new FileWriter("test.txt");
      fw.write("abcd");
      fw.flush();
    }
  catch(IOException e){
   
  }

 ③当new FileWriter("test.txt")发生异常,此时fw依然为null
   那么下面fw.close()将引发NullPointerException
   对此在fw.close()之前加上if(fw!=null)
   如果多个流分别关(多个if判断)
*/

4.   FileWriter(String fileName, boolean append) :

/*
对已有文件的内容进行续写
把新的内容添加到文件的结尾
利用FileWriter中的
   FileWriter(String fileName, boolean append) 
     根据给定的文件名以及指示是否附加写入数据的boolean值来构造 FileWriter 对象。
  append - 一个 boolean 值,如果为 true,则将数据写入文件末尾处,
            而不是写入文件开始处。 
*/
package filewriter;
import java.io.FileWriter;
import java.io.IOException;
class FileWriterDemo3{
   public static void main(String[] args){
    
       
       FileWriter fw = null;
       try{
         fw=new FileWriter("test.txt",true);//传递一个true参数,代表将不覆盖已有文件(若不存在
                                            //该文件,则会创建)并在已有文件末尾处进行续写
         fw.write("\r\nheixiu");//在windows下实现换行为两个字符\r\n,单独\r,\n无效果         
       } 
       catch(IOException e){
        System.out.println(e.toString());
       }
       finally{
         try{
           if(fw!=null)
            fw.close();
         }
         catch(IOException e){
           System.out.println(e.toString());
         }
       }
   }
}

5.FileReader:

   

package filereader;
import java.io.FileReader;
import java.io.IOException;
import java.io.FileNotFoundException;
import static java.lang.System.out;
class FileReaderDemo{
    public static void main(String[] args){
    //创建一个文件读取流对象,和指定名称的文件相关联
    //要保证该文件是已经存在的,如果不存在,会抛出FileNotFoundException(IOException子类)
    
     FileReader fr=null;
     try{
      fr = new FileReader("test.txt");//文本内容为b
      
      int ch=0;
        
       while((ch=fr.read())!=-1)
        out.println((char)ch);
      /*
       read()读取单个字符,一次读一个字符,会自动往下读
       作为整数读取的字符,范围在0到65535之间(0x00-0xffff,char的范围),
       
       如果已到达流的末尾,则返回 -1 
     */
     }
     catch(IOException e){
      e.printStackTrace();
     }
      finally{
        try{
        if(fr!=null)
         fr.close();
        
        }
        catch(IOException e){
         out.println(e.toString());
        }
      }
    }
} 
/*
关于字符:
ascll码中:128-255是IBM-PC上专用的。000-127是标准 
也就是说:
out.println((char)128);//?
out.println((char)-1);//? //-1补码全1->强转为char->后16位全1(正)->2^16-1(65535)
*/

read()

6.Reader:public int read(char[] cbuf) throws IOException

/*
 public int read(char[] cbuf) throws IOException
 功能:将字符读入数组
 返回:读取的字符数,如果已到达流的末尾,则返回 -1
 (画一个示意图)
*/
package filereader;
import java.io.FileReader;
import java.io.IOException;
import static java.lang.System.out;
class FileReaderDemo2{
  public static void main(String[] args)throws IOException{
  
   FileReader fr = new FileReader("test.txt");//文件内容abcdefg   
   char[] buf = new char[3];//定义数组长度为3,通常定义为1024的整数倍
   
   int num=0;
  
   
   while((num=fr.read(buf))!=-1)
     out.println(num+"..."+new String(buf,0,num));
   fr.close();
  }
}
read(char[] cbuf)_abcdefg

 

read(char[] cbuf)

7.练习:read(char[] buf):

 

/*
 读取一个.java文件打印到控制台上
*/
package filereader;
import java.io.FileReader;
import java.io.IOException;
import java.io.FileNotFoundException;
import static java.lang.System.out;
class FileReaderTest{
    public static void main(String[] args){
     FileReader fr =null;
     try{
       fr=new FileReader("7_FileReaderTest.java");//当前java文件
       char[] buf = new char[1024]; 
       int readNum=0;
       while((readNum=fr.read(buf))!=-1)
           out.println(new String(buf,0,readNum));//分配一个新的 String,它包含取自字符数组参数一个子数组的字符。offset (第二个)参数是子数组第一个字符的索引,count(第三个)参数指定子数组的长度。
     }
     catch(IOException e){
       e.printStackTrace();
     }
     finally{
       try{
       if(fr!=null)
          fr.close();
       }
       catch(IOException e){
        e.printStackTrace();
       }
     }
    }
}
读取 一个.java文件

8.文件拷贝:

/*
将C盘一个文本文件复制到D盘
其实就是将C盘下的文件数据存储到D盘的一个文件中
步骤:
1.在D盘创建一个文件,用于存储c盘文件中的数据
2.定义读取流和c盘文件关联.
3.通过不断读写完成数据存储
4.关闭资源.
 (画一个示意图)
*/
package copy;
import static java.lang.System.out;
import java.io.IOException;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.FileReader;
class FileReaderTest2{
  public static void copy(String fileName,String destPath){
  FileReader fr=null;
  FileWriter fw=null;
  char[] buf = new char[1024];
  try{
    fr=new FileReader(fileName);
    String[] str=fileName.split("\\\\");//regex为\\\\,因为在java中\\表示一个\,而regex中\\也表示\,所以当\\\\解析成regex的时候为\\。
                                       //正则表达式内容
    fw=new FileWriter(destPath+str[str.length-1]);//以上分割成路径+文件名 两部分,可能路径有多级目录c:\\xx\\xx\\aa.txt
    int len=0;
    while((len=fr.read(buf))!=-1)
      fw.write(buf,0,len);//从数组0角标开始,读length=num个字符
  }                       //假如只有4个字符,如果用write(buf)将把4+1020个全写入流中,因此需要只写读到的.
  catch(IOException e){
    throw new RuntimeException("读写失败");//停掉程序
  }
  finally{
   if(fr!=null)
   try{
    fr.close();
    }
   catch(IOException e){
    e.printStackTrace();
   }
   if(fw!=null)
   try{
    fw.close();
    }
   catch(IOException e){
    e.printStackTrace();
   }
  }
}
/*
也可利用读一个写一个(但是循环次数增多,效率低)
 int ch=0;
 while((ch=fr.read())!=-1)
   fw.write(ch);
*/
public static void main(String[] args) {
   
    copy("c:\\abc.txt","e:\\");
 }


}

以上示意图:

文件复制过程

posted @ 2013-05-01 21:48  伊秋  阅读(444)  评论(0编辑  收藏  举报