天天看点

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倍

        int len = ;
        while( (len = fis.read(by))!= ){
            System.out.print(new String(by , , 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倍

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

fis.close() ;
           

继续阅读