黑马程序员_<<字节流(含子类)和字节缓冲流(InputStream,OutputStream,BufferedInputStream,BufferedOutputStream)>>

--------------------ASP.Net+Android+IOS开发.Net培训、期待与您交流! --------------------


1.字节流

字符流:Writer,Reader 主要是用来操作的是文本文件

字节流:InputStream,OutputStream主要是用来操作的是媒体文件,例如:图片,音乐,电影…等。但是也可以操作文件。

 

如果用字符流操作媒体文件的话,复制文件的话:也能复制,只是复制后的图片不能看,因为查看的编码是不一样的,

不管是读还是写,都不需要刷新缓冲,除非用到了缓冲对象。

2. FileOutStream

     操作文件,向文本文件中写入数据,其没有写入字符串耳朵方法,有字节数组的写入,所以我们要把字符串转换成数组。然后写入。

 

 

importjava.io.FileNotFoundException;
importjava.io.FileOutputStream;
importjava.io.IOException;
importjava.io.OutputStream;
 
public classOutStreamDemo {
      public static void main(String[]args)  {
           OutputStream out=null;
           try {
                 out=new FileOutputStream("F:\\demo.txt");
                 out.write("helloworld".getBytes());//写入数据,把字符串转换为字节数组
           } catch (IOException e) {
                 e.printStackTrace();
           }finally{
                 if(out!=null){
                      try {
                            out.close();
                      } catch (IOException e) {
                            e.printStackTrace();
                      }
                 }
           }
      }
 
}


3.     FileInputStream

读取文件,有三种方法,

第一种:一个一个字符的读取,

第二种:字节数组的读取。

第三种:使用available()方法,读取到文件的总大小,然后定义相同大小的字节数组,读取一次即可,但是加入文件过大,大于了虚拟的内存的大小,那么就会加载不进去,所以最好的办法是定义恰当合适的数组,然后循环读取。
 

          1.  单个字节读取

使用的read()方法,进行循环读取。

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
 
public class InputStreamDemo {
  public static void main(String[] args) {
    InputStream in = null;
    try {
      in = new FileInputStream("F:\\demo.txt");
      /* 这个为一个一个的读取,使用read()方法,然后读取到的字符的ASCII码,到结尾就返回-1*/
      int r = -1;
      while ((r = in.read()) != -1) {//开始读取
         System.out.print((char) r);
      }
    } catch (IOException e) {
      e.printStackTrace();
    }finally{
      if(in!=null){
         try {
           in.close();//关闭流
         } catch (IOException e) {
           e.printStackTrace();
         }
      }
    }
  }
 
}


         2.  字节数组读取

定义恰当的数组,然后循环读取 使用的read(byte [] b)
然后转换成字符串,返回。

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
 
public class InputStreamDemo {
  public static void main(String[] args) {
    InputStream in= null;
    try {
      in= new FileInputStream("F:\\demo.txt");
      /* 使用字节数组读取,然后转成字符串。到结尾就返回-1*/
      byte [] b=new byte[1024];
      int len=-1;
      while ((len = in.read(b)) != -1) {//开始读取
         System.out.print(new String(b,0,len));
      }
    } catch (IOException e) {
      e.printStackTrace();
    }finally{
      if(in!=null){
         try {
           in.close();//关闭流
         } catch (IOException e) {
           e.printStackTrace();
         }
      }
    }
  }
 
}


 

           3.  固定数组大小

使用的available()方法,读取到文件的大小,然后定义相应的大小的字节数组,如果文件小的话,可以这样使用,但是文件很大,超过了虚拟机的申请的内存,那么就会导致加载不进入,所以最好的方法是是哟第二种方法,定义合适的字节数组的大小。
 

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
 
public class InputStreamDemo {
  public static void main(String[] args) {
    InputStream in = null;
    try {
      in = new FileInputStream("F:\\demo.txt");
      /* 使用字节数组读取,数组的大小用:available()方法定,然后转成字符串。到结尾就返回-1 */
      byte[] b = new byte[in.available()];
      int len = in.read(b);
      System.out.print(new String(b, 0,len));
 
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      if (in != null) {
         try {
           in.close();// 关闭流
         } catch (IOException e) {
           e.printStackTrace();
         }
      }
    }
  }
 
}


 

4. 复制图片

     使用的InputStream和OutputStream

     步骤:

     1.使用读取流InputStream,与要读取的图片关联。

     2.定义写入流,定义好复制到的位置和图片的名称。

     3.然后一边读取一边写入,循环读取和循环写入。使用的是数组读取和写入。

     4.最后关闭流。

   扩展:复制后的文件名称可以改变也可以不变,格式也可以改变,jpg或者bmp.或者其他的格式都可以

 

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
 
public class OutAndInputStreamDemo {
  public static void main(String[] args) {
    InputStream in = null;// 读取流字节流
    OutputStream out = null;// 写入流字节流
    try {
      in = new FileInputStream("F:\\A\\1.jpg");// 与复制的图片关联起来
      out = new FileOutputStream("F:\\B\\1.bmp");// 与复制到的目的关联起来,这里的图片的名称可以与原来的相同,也可以不一样
      byte[] b = new byte[1024];// 定义字节数组,并指定长度
      int l = -1;
      while ((l = in.read(b)) != -1) {// 读取
         out.write(b, 0, l);// 写入,读多少写入多少,所以用 write(b,0,len)
      }
      System.out.println("复制成功");
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      if (in != null) {
         try {
           in.close();// 关闭读取流
         } catch (IOException e) {
           System.out.println("读取流关闭失败");
         }
         if (out != null) {
           try {
             out.close();// 关闭写入流
           } catch (IOException e) {
             System.out.println("写入流关闭失败");
           }
         }
      }
 
    }
  }
 
}
结果:
复制成功


5. 字节流的缓冲

      字符流:Writer,Reader

             BufferedWriter和BufferedReader

字节流:InputStream,OutputStream体文

                    BufferedInputStream和BufferedOutputStream

 

字节流的缓冲和字符流的花冲使用方法是类似的,用的对象是BufferedInputStream和BufferedOutputStream,他们增强了字节流的读取和写入效率。

         1.  利用缓冲对象复制MP3文件

 

package www.fuxi.IO;
 
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
 
public class BufferedStreamDemo {
  public static void main(String[] args) {
    BufferedInputStream bis = null;// 读取缓冲流
    BufferedOutputStream bos = null;// 写入缓冲流
    try {
      bis = new BufferedInputStream(new FileInputStream("F:\\A\\1.mp3"));// 要复制的MP3文件
      bos = new BufferedOutputStream(new FileOutputStream("F:\\B\\1.mp3"));// 复制到的目的地
      byte[] b = new byte[1024];
      int len = 0;
      while ((len = bis.read(b)) != -1) {// 读取
         bos.write(b, 0, len);// 写入
      }
      System.out.println("复制成功");
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      if (bis != null) {
         try {
           bis.close();// 关闭读取缓冲对象流
         } catch (IOException e) {
           e.printStackTrace();
         }
         if (bos != null) {
           try {
             bos.close();// 关闭写入缓冲对象流
           } catch (IOException e) {
             e.printStackTrace();
           }
         }
      }
    }
  }
 
}
结果:
复制成功


         2.  模拟读取缓冲区

 

import java.io.IOException;
import java.io.InputStream;
 
public class MyBufferedInputStream {
   privateInputStream in = null;
   private intcount = 0;// 计数器
   private intpos = 0;// 指针
   private byte[]bu = new byte[1024];// 封装的字节数组
 
   publicMyBufferedInputStream(InputStream in) {
        this.in =in;
   }
 
   public intMyRead() throws IOException {
 
        if (count== 0) {// 说明此时缓冲区中没有数据,可能是缓冲区中还没有开始读取,或者是缓冲区中数据读取完毕
              count= in.read(bu);// 向缓冲区中读取数据
              if(count < 0) {
                   return-1;// 这里返回的是int类型的-1
              }
              pos=0;//每次把指针都初始化
              byteb = bu[pos];
              count--;//计数器减一
              pos++;//指针加一
              returnb & 0xff;// 这里b是byte类型,自动提升为整形,但是前面补充的是全是1,为了防止当读取道德byte数据为11111111时,&上0xff,那么使前面的是0,那么这样额可以是原数据不变,又能避免字节数据是-1的情况
 
        } elseif(count>0){
              byteb = bu[pos];
              count--;//计数器减一
              pos++;//指针加一
              returnb & 0xff;// 这里b是byte类型,自动提升为整形,但是前面补充的是全是1,为了防止当读取道德byte数据为11111111时,&上0xff,那么使前面的是0,那么这样额可以是原数据不变,又能避免字节数据是-1的情况
        }
        return-1;
   }
 
   public voidmyClose() throws IOException {
        in.close();
   }
}
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/*
 *测试类,也是复制MP3*/
public class BufferedStreamDemo {
  public static void main(String[] args) {
    MyBufferedInputStream bis = null;// 读取缓冲流
    BufferedOutputStream bos = null;// 写入缓冲流
    try {
      bis = new MyBufferedInputStream(new FileInputStream("F:\\A\\1.mp3"));// 要复制的MP3文件
      bos = new BufferedOutputStream(new FileOutputStream("F:\\B\\1.mp3"));// 复制到的目的地
      // byte[] b = new byte[1024];
      int r = 0;
      while ((r = bis.MyRead()) != -1) {// 读取
         bos.write(r);// 写入
      }
      System.out.println("复制成功");
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      if (bis != null) {
         try {
           bis.myClose();// 关闭读取缓冲对象流
         } catch (IOException e) {
           e.printStackTrace();
         }
         if (bos != null) {
           try {
             bos.close();// 关闭写入缓冲对象流
           } catch (IOException e) {
             e.printStackTrace();
           }
         }
      }
    }
  }
 
}
 
结果:复制成功


 

注意点:在MyRead()方法中return 返回的必须写b&0xff,因为这样byte类型的提升为整形后,可以保证原数据保持不变,把原来的数据前面相当于添加的0.

例如:

byte  : 11111111  这是-1

自动提升为整形后的数据是

        1111111111111111 11111111 11111111 此时这是-1

那么当byte类型的数据是八个1的时候,那么直接返回b,那么提升为整形后是四个八个1,那么还是-1,所以程序直接结束,读取完毕,解决方法是,要是在前面补充的是全是0的话,那么原数据不变没这样也避免的读取-1的情况。

      1111111111111111 11111111 11111111

&     00000000 00000000 00000000 11111111 这是255,

-----------------------------------------------------------------

      0000000000000000 00000000 11111111

 

所以这样结果就是我们想要的数据,既避免了读取byte是11111111的缺点,同时还保证了原数据不变。

Read方法是byte类型的提升,从1个字节提升为整形为四个字节。Write方法是把4个字节变成了1个字节,值去最后的一个字节。所以复制后的文件的大小和原来的大小一下,而不是其4倍的大小。

6. 键盘读取

  

   import java.io.IOException;
import java.io.InputStream;
 
public class ClassDemo {
  public static void main(String[] args) throws IOException {
    /*
     * InputStream in“标准”输入流:读取的设备是键盘 PrintStream out“标准”输出流。输出到控制台
     */
    /*
     * 我们可以循环输入,当输入为over时候,结束输入
     */
    InputStream in = System.in;
    StringBuilder bu= new StringBuilder();
    while (true) {
      int ch = in.read();
      if (ch == '\r')
         continue;
      if (ch == '\n') {
         String s = bu.toString();
         if ("over".equals(s))// 如果输入的是over,那么结束输入
           break;
         System.out.println("输入的内容是:" + s);
         bu.delete(0,bu.length());
      } else
         bu.append((char) ch);
    }
 
  }
 
}
结果:
aa
输入的内容是:aa
bb
输入的内容是:bb
cc
输入的内容是:cc
over

 


--------------------ASP.Net+Android+IOS开发.Net培训、期待与您交流! --------------------

 


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值