JAVA学习笔记——IO流(字节流)

1.IO流用来解决设备间的数据传输问题。
2.IO流的分类
  按流的方向:
    输入流:读取数据
    输出流:写出数据
  按数据类型:
    字节流
      字节输入流:读取数据 InputStream
      字节输出流:写出数据 OutputSteam
    字符流
      字符输入流:读取数据 Reader
      字符输出流:写出数据 Writer
  什么情况下使用哪种流呢?
    如果数据所在的文件通过Windows自带的文件夹可以打开并且能够读懂里面的内容,就用字符流。其他用字节流
    如果什么都不知道,就用字节流。
  注意:InputSteam和OutputSteam都是抽象类(abseract),不能直接用,需要使用它们具体的子类。
  其实现类主要有以下:
  InputStream:FileInputStream, FilterInputStream,StringBufferInputStream 等
  OutputStream: FileOutputStream, FilterOutputStream 等
  注意:每种基类的子类都是以父类名作为后缀名
  
3. 字节输出流FileOutputSteam
  构造函数:
    public void FileOutputStream(File file) :创建一个指向该file文件的字节输出流对象
    public void FileOutputStream(String name) :创建一个指向该路径的字节输出流对象
    public void FileOutputStream(File file, boolean append) :创建一个指向该file文件的字节输出流对象,如果append值为true,则将字节写到文件末尾处,否则会覆盖原来的。
    public void FileOutputStream(String name, boolean append) :创建一个指向该路径的字节输出流对象,如果append值为true,则将字节写到文件末尾处,否则会覆盖原来的。
  写数据方法:
    public void write(byte[] b) :写一个字节
    public void write(int b) :写一个字节数组
    public void write(byte[] b, int off, int len) :写一个字节数组的一部分
  使用步骤:
    A:创建字节输出流对象
      FileOutputSteam fos = new FileOutputSteam(“fos.txt”) ;
       此处字节输出流做了几件事情:
       1)如果不存在该文件,则调用系统功能去创建该文件,如果存在则不做这件事
       2)创建fos对象
       3)把fos指向这个文件
       
    B:写数据
      fos.write( “Hello.IO”.getBytes() ) ;
       此处用的方法是 void write(byte[] b) ; 可见参数是一个字节数组,因此要把字符串转换为字节数组。
       
    C:释放资源
      fos.close() ;
       为什么一定要close()呢?
       1)让流对象变成垃圾,这样就可以被垃圾回收器回收
       2)通知系统去释放跟该文件相关的资源(这点很重要)
  
  问题1:如何在写入的时候实现换行?
    很简单,只需要在写入字节流的时候同时写入换行符即可。但是不同系统的换行符是不同的,
    Windows:\r\n
    Linux:\n
    Mac:\n
    而一些常见的高级记事本是可以识别任意换行符的。
  
  使用IO流的过程中需要注意的事会需要加入异常处理,因此上述代码的最终完美版应该事下面这样:

FileOutputStream fos = null ;   //这里不赋值为null的话close()方法会报错
try{
    fos = new FileOutputStream("fos.txt") ;  //如果是绝对路径,这里可能会出现找不到路径的情况,即FileNotFoundException异常
    fos.write("hello.IO".getBytes());  //这里可能会报IOException的异常
}catch(FileNotFoundException e){   
    e.printStackTrace();
}catch (IOException e) {
    e.printStackTrace();
}finally{     //为了防止上面两步出错导致字节流无法运行close()方法,把关闭字节流方法写到finally中即可。
    if(fos != null)   //如果第一步找不到路径的话fos就会为空,那么对象调用close()方法就会无意义,因此为了防止这种情况,加入一个判断
        try {
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
}

4、字节输入流FileInputStream
  构造方法
    public FileInputStream(File file) :
    public FileInputStream(String name) :
  读取方法:
    int read():一次读取一个字节,读到文件结尾的话返回-1
    int read(byte[] b):一次读取一个字节数组,返回的结果是实际读取到的数据的长度,读到文件结尾则返回-1
  读取步骤:
    A:创建字节输入流对象
      FileInputStream fis = new FileInputStream (“fis.txt”) ;
    B:调用read()方法读取数据,并返回该字节对应的int值
      int b = fis.read() ;
    C:释放资源
      fis.close() ;
    因为read()方法一次指读取一个字节,所以要用循环判断来读取。如下:
    int b = 0 ;
    while(int b = fis.read() != -1){
      System.out.print((char) b) ;
    }
    注意:这里只能读取数字和英文字符,不能读取中文汉字,因为汉子占用两个字节,这样读取到的汉子都是乱码,因此才会出现字符流。
    在计算机中中文存储用的两个字节,其中
      第一个字节肯定是负数,
      第二个字节常见的是负数,可能有负数,但是没影响。

  但是,实际用中并不常用read()来进行单字节读取,通常是使用read(byte[] b)方法,这样的效率会比单字节读取速度提升字节数组的长度倍(理论上)。其最终版代码如下:

        FileInputStream fis = new FileInputStream("fis.txt") ;

        byte[] by = new byte[1024] ;  //这里的字节数组长度通常设置为1024或者1024的倍数,理论上速度提高1024倍

        int len = 0 ;
        while( (len = fis.read(by))!= -1 ){
            System.out.print(new String(by , 0 , len)); //这里一定要用0-len的长度输出,防止最后一次读取只能更新字节数组的前面一部分。
        }

        fis.close() ;

    
5. 由上我们可以看到设置一个数组作为缓冲区确实可以提高读写效率
 既然这样的的话,Java在开始设计的时候也采用的这样的思想,提供了一种带缓冲区的字节类。这种类被称为缓冲区类(高效类)。
 写数据:BufferOutputStream
   构造方法:
     BufferOutputStream(OutputStream out) :创建一个缓冲输出流,把数据写入指定的底层输出流
     BufferOutputStream(OutputStream out , int size):创建一个指定大小的缓冲输出流,把数据写入指定的底层输出流
     注意:为什么不直接指定具体的文件或者路径而是指定一个输出流对象呢?
       因为字符缓冲流仅仅提供缓冲区,为高效设计的,但是真正的读写还是要靠基本的流对象来实现。
     

BufferOutputStream bos = new BufferOutputStream(new FileOutputStream("bos.txt")) ; //通常采用匿名对象方法

bos.write("hello".getBytes());

bos.close() ;

 读数据:BufferInputStream
   构造方法:
     BufferInputStream(InputStream in) :创建一个缓冲输入流
     BufferInputStream(InputStream in , int size):创建一个指定大小的缓冲输入流

BufferInputStream bis= new BufferInputStream(new BufferInputStream("bis.txt")) ;

byte[] by = new byte[1024] ;  //这里的字节数组长度通常设置为1024或者1024的倍数,理论上速度提高1024倍

int len = 0 ;
while( (len = bis.read(by))!= -1 ){
    System.out.print(new String(by , 0 , len)); //这里一定要用0-len的长度输出,防止最后一次读取只能更新字节数组的前面一部分。
}

fis.close() ;

你可能感兴趣的:(Java开发--学习阶段,字节流,IO,InputStream,OutputStream)