天天看点

黑马程序员————IO流——字节流



------<a href="http://www.itheima.com" target="_blank" rel="external nofollow" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------

IO流——字节流

一.IO流:

 1、IO流的类的层次结构

A:字节流: 
   OutputStream:
      |--FileOutputStream:
      |--FilterOutputStream:(没学)
          |--BufferedOutputStream:(带缓冲区字节流)
   InputStream:
      |--FileInputStream:
      |--FilterInputStream:(没学)
         |--BufferedInputStream(带缓冲区字节流)
B:字符流:
   Writer:
     |--OutputStreamWriter(转换流)
        |--FileWriter:
     |--BufferedWriter(带缓冲区字符流)
   Reader:
     |--InputStreamReader(转换流)
        |--FileReader:
     |--BufferedReader:(带缓冲区的字符流)
           

 2.IO流概念:

  1).IO流:InputStream和OutputStream

  2).流:是有方向的,线性的;针对某个文件的输入输出流

     站在程序的角度:

          InputStream :从外部向程序中读入数据的

          OutputStream:从程序向外部输出数据

  3).分类:

      A.按流向:

            输出流

            输入流

      B.按读写方式:

            字节流:

            字符流:

二、FileOutputStream(类,继承自OutputStream抽象类)(文件可以不存在)

1.构造方法:

  覆盖写:

        FileOutputStream(String name):使用一个文件名构造一个输出流

        例子:FileOutputStream file=new FileOutputStream("D:\\aaa\\output.txt");

        FileOutputStream(File file);使用一个文件类型的引用构造一个输出流

        例子:FileOutputStream file=new FileOutputStream(new File("output.txt"));

   对于上述的例子中的文件既可以是绝对路径也可以是相对路径,相对路径就会在当前工作目录创建文件。

   这里会有一场出现,会在不能创建文件(磁盘问题,权限问题等)时出现异常,使用try...catch语句抛出异常即可

  追加写:

         FileOutputStream(String name,boolean append):

         FileOutputStream(File file,boolean append);追加写入,当判断为真时,在文件的末位。

 2.写入方法:

  A:public void write(int byte):向文件中写入一个字节。因此byte必须在字节的范围之内,即-128~127.但是负值有可能没有对应值。

  B:public viod write(byte[] byteArray):写入一个字节数组。

   ★★★如何把一个字符串转化为一个字节数组呢?使用String类的getBytes()方法获取字节数组byte[]

  C:public void write(byte[] byteArray,int off,int len):只写数组的一部分

 3.关闭流:

  close();关闭通道,结余资源,不然一直占用其他文件无法访问。

 4.输出换行符

  out.write("\r\n".getBytes());

★★5.加入异常处理

  1).直接在方法声明上抛出异常(不推荐)

  2).try..catch单组捕获异常

  3).try..catch 多组组合捕获异常

public class Demo {
   public static void main(String[] args) {
  	FileOutputStream out = null;
  	try {
    	     out = new FileOutputStream("output2.txt",true);//可能产生异常
   	     //写入数据
  	     out.write("你好Java".getBytes());//可能产生异常
  	     out.write("\r\n".getBytes());//可能产生异常
   
  	} catch (FileNotFoundException e) {
   	     System.out.println("无法创建系统文件,请查看您是否有权限访问磁盘,或查看磁盘空间是否够用!");
  	} catch (IOException e) {
   	     System.out.println("无法写入系统文件,请联系系统管理员!");
  	}finally{
  	 //释放资源
   	try {
   	     if(out != null){
    	 	out.close();
   	     }
  	 } catch (IOException e) {
    		System.out.println("无法关闭系统文件,请联系系统管理员!");
   	 }
 	}
  
    }
} 
           

三、FileInputStream(类,继承自InputStream)(文件必须存在,抛出异常:java.io.FileNotFoundException)

  1.构造方法:

         FileInputStream(String name):使用文件名创建一个输入流

         FileInputStream(File file):使用一个文件类型的引用创建一个输入流

  2.读取的方法:

   public int read();一次读取一个字节,返回一个Int值,可以打印,可以用char强转,但是可能没有意义。

   当读取到文件的末位时,会返回-1。可以读取换行符。在eclipse里面会显示是\r\n,是两个换行符。

   两种常用的循环遍历的方法:

方法一:
    int m=in.read();
    while(m!=-1){
        System.out.println(m+""+char(m));}
        m=in.read();
    方法二:
    int m=0;
    while((m=in.read())!=-1){
        System.out.println(m+""+char(m));}
  
           

  3.复制一个文本文件案例(用来做加密文字比较好啊)

   思路分析:

          1).从源文件读取数据,使用输入流

          2).一次读取一个字节

         3).向目标文件写入输出一个字节

             代码实现:

public class Demo {
   public static void main(String[] args)  {
 	 try {
   	     //创建一个输入流对象
   	     FileInputStream in=new FileInputStream("D:\\day20-copy.text");
   	     //创建一个输出流对象
   	     FileOutputStream out=new FileOutputStream("D:\\day20-copy1.java");
   	     //读取一个字节
   	     int n=0;
   	     while((n=in.read())!=-1){
   		 System.out.println(n+""+(char)n);
    		 out.write(n);
    
    	     }
   	     in.close();
             out.close();
  	    } catch (FileNotFoundException e) {
  		 System.out.println("捕获输入输出异常");
   		 e.printStackTrace();
  	    } catch (IOException e) {
  		 System.out.println("捕获读取写入异常");
   		 e.printStackTrace();
 	    }
  	   System.out.println("程序执行完毕!!!");
 	}
}   
           

   4.第二种读取方法:public int read(byte[] byteArray):

   ★★★如何打印字节数组的内容呢?

   很简单的,Array.toString(byteArray),其打印结果是,用[]括起来的,用逗号分隔的数组元素的字符串。

   ★★★使用String的构造方法,可以将一个byte数组转换为一个字符串。

   String(byte[] bytes)

   String(byte[] bytes, int offset, int length)

   读取到文本底部时,返回值也是-1.

   基本使用方法:

//创建一个字符数组
   byte[] byteArray=new byte[20];一般根据需要定义数组的长度
   int n=0;
   while((n=in.read(byteArray))!=-1){
    String s=new String(byteArray,0,n);//此种的构造方法,可以恰到好处的取出全部的内容★★
    ★★//实际上n代表的就是数组中被再次填入的元素个数,最后一次填入,可能填不满,但是原来的元素不会被全部覆盖。
    System.out.println(s);
   }
           

   一次读取一个字节数组,复制文本文件。视频同样方法。代码实现:

public class Demo {
 public static void main(String[] args) throws IOException {
  //1.文件的输入流:文件必须存在,否则抛出异常
  FileInputStream in = new FileInputStream("D:\\aaa\\StringDemo.java");
  //2.文件的输出流:文件可以不存在。如果不存在,则创建
  FileOutputStream out = new FileOutputStream("StringDemo_demo02_copy.java");
  
  //开始复制:
  //一次读取一个字节数组
  byte[] byteArray = new byte[1024];
  int n = 0;
  while((n = in.read(byteArray)) != -1){
   //写入,一次写入一个byte数组
   out.write(byteArray, 0, n);
  }
  //释放资源
  in.close();
  out.close();
  System.out.println("复制完毕!下课");
 }
}
           

四、带缓冲的字节流

  1.缓冲的字节流概述

   可以看到使用字节数组可以大大加快复制速度,由于数组具有缓冲区功能。一次读取的数据填充到数组中,然后再一次写入,提高了效率。

  2.带缓冲的字节流

   BufferedInputStream;带缓冲的输入流

   BufferedOutputStream;带缓冲的输出流

  3.带缓冲的输出流:BufferedOutputStream

   BufferedOutputStream:带缓冲的输出流:只要是OutputStream的子类都可以,我们学过:FileOutputStream;

   BufferedOutputStream只提供了"缓冲区",只是写进了内存去,内部写入,仍然使用参数传递的FileOutputStream对象实现。

   BufferedOutputStream(OutputStream out) :创建一个新的缓冲输出流,以将数据写入指定的底层输出流。

   BufferedOutputStream(OutputStream out, int size) 创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流。

   输出流的写入的方法:它没有特有的写入方法,使用父类的即可

   注意:如果要实现追加写的话,就要在构建OutputStream时准备好。

      flush(),刷新缓冲区,实现写入功能。

      close(),内部集成了刷新功能,可以不用再刷新了。

  4.带缓冲的输入流:BufferedInputStream

   BufferedInputStream(InputStream in) : 创建一个 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。

   BufferedInputStream(InputStream in, int size) : 创建具有指定缓冲区大小的 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。

   没有特有方法,使用父类的方法

    int read():读取一个字节

    int read(byte[] byteArray):读取一个字节数组

  5.五种方式复制文件速度对比

   1.一次读、写一个字节:使用基本流:FileInputStream 和 FileOutputStream -- > method1():  57626毫秒

   2.一次读、写一个字节数组:使用基本流:FileInputStream 和 FileOutputStream --> method2();  149 毫秒

   3.一次读、写一个字节:缓冲流:BufferdInputStream 和 BufferedOutputStream --> method3(); 958 毫秒

   4.一次读、写一个字节数组:缓冲流:BufferdInputStream 和 BufferedOutputStream --> method4(); 66 毫秒

   结论:读写"二进制"文件,首选带缓冲的字节流。

//1.一次读、写一个字节:使用基本流:FileInputStream 和 FileOutputStream -- > method1()
 private static void method1() throws IOException{
  FileInputStream in = new FileInputStream("D:\\aaa\\哥有老婆.mp4");
  FileOutputStream out = new FileOutputStream("哥有老婆_copy1.mp4");
  
  //开始复制,一次读写一个字节
  int n = 0;
  while((n = in.read()) != -1){
   out.write(n);//写入一个字节
  }
  //释放资源
  in.close();
  out.close();
  
 }
           
//2.一次读、写一个字节数组:使用基本流:FileInputStream 和 FileOutputStream --> method2();
 private static void method2() throws IOException{
  FileInputStream in = new FileInputStream("D:\\aaa\\哥有老婆.mp4");
  FileOutputStream out = new FileOutputStream("哥有老婆_copy2.mp4");
  
  //开始复制,一次读写一个字节数组
  byte[] byteArray = new byte[1024];
  int n = 0;
  while((n = in.read(byteArray)) != -1){
   out.write(byteArray,0,n);//一次写入一个字节数组
  // out.flush();
  }
  //释放资源
  in.close();
  out.close();
 }
           
//3.一次读、写一个字节:缓冲流:BufferdInputStream 和 BufferedOutputStream --> method3()
 private static void method3() throws IOException{
  BufferedInputStream in = new BufferedInputStream(new FileInputStream("D:\\aaa\\哥有老婆.mp4"));
  BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream("哥有老婆_copy3.mp4"));
  
  //一次读、写一个字节
  int n = 0;
  while((n = in.read()) != -1){
   out.write(n);
  }
  //释放资源
  in.close();
  out.close();
 }
           
//4.一次读、写一个字节数组:缓冲流:BufferdInputStream 和 BufferedOutputStream --> method4();
 private static void method4() throws IOException {
  BufferedInputStream in = new BufferedInputStream(new FileInputStream("D:\\aaa\\哥有老婆.mp4"));
  BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream("哥有老婆_copy3.mp4"));
  
  //一次读、写一个字节数组
  byte[] byteArray = new byte[1024];
  int n = 0;
  while((n = in.read(byteArray)) != -1){
   out.write(byteArray,0,n);
  }
  //释放资源
  in.close();
  out.close();
 }