IO流之输出流总结

白昼怎懂夜的黑 提交于 2019-12-23 03:46:35

学习真的是忘了学,学了忘的过程,学的好多东西都忘了,又要重新复习,好在之前都有做较为详细的笔记,可以及时的拿来复习,如果没有做笔记,转而再去听视频,会很浪费时间,听视频效果也没有看笔记效果好,而且更节省时间,所以关于这个IO流的总结,我会写的尽量的详细,以便后来进行复习。

1. 什么是流?

  1. 流的概念:
    java的IO流是实现输入输出的基础,可以方便的实现数据的输入和输出操作。
    在java中把不同的输入输出源(键盘,文件,网络连接等)抽象的表述为流
    通过流的方式允许java程序使用相同的方式来访问不同的输入和输出源。
  2. 流的分类:
    输入流:能够从中读取数据的设备
    输出流:能够向其写入数据的设备
  3. 如何区分输入流和输出流???
    这是一个很容易搞混的问题,划分输入流和输出流是从内存的角度来划分的。
    比如这张图,从内存的角度,内存向硬盘(输出流)写入数据
    在这里插入图片描述
    再比如这张图,站在内存的角度来看,左边是从输入流中读取数据到内存,右边是向输出流中写入数据。
    在这里插入图片描述
  4. 输入流和输出流
    输入流:InputStream和Reader
    输出流:OutputStream和Writer
    以上四个类都是抽象类,不可实例化,需要子类继承他们。

2. 字节文件输出流(FileOutputStream)

  1. 什么是字节文件输出流??
    所谓的字节文件输出流,就是指将字节数据从内存中写入文件中
    在这里插入图片描述

  2. 字节文件输出流的构造方法:
    (1)创建一个向指定 File 对象表示的文件中写入数据的文件输出流:
      public FileOutputStream(File file)
    (2)创建一个向指定 File 对象表示的文件中写入数据的文件输出流。如果第二个参数为 true,则将字节写入文件末尾处,而不是写入文件开始处:
      public FileOutputStream(File file, boolean append)
    (3)创建一个向具有指定名称的文件中写入数据的输出文件流:
      public FileOutputStream(String name)
    (4)创建一个向具有指定 name 的文件中写入数据的输出文件流。如果第二个参数为 true,则将字节写入文件末尾处,而不是写入文件开始处:
      public FileOutputStream(String name,boolean append)
      
    注意:并且写入文件不需要文件已经存在。如果该文件存在,但它是一个目录,而不是一个常规文件;或者该文件不存在,但无法创建它;抑或因为其他某些原因而无法打开它,则抛出 FileNotFoundException。

  3. 字节文件输出流的常用方法:
    (1)将 b.length 个字节从指定 byte 数组写入此文件输出流中:
      public void write(byte[] b)
    (2)将指定字节写入此文件输出流。
      public void write(int b)
    (3)将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流
      public void write(byte[] b,int off,int len)
    (4)关闭此文件输出流并释放与此流有关的所有系统资源。此文件输出流不能再用于写入字节
      public void close()
      
    注意:以上的四个方法均为覆盖 OutputStream 的中的方法

例1:向文件fos.txt中写入数据hello,io

public class FileOutputStreamDemo
{
    public static void main(String[] args) throws IOException, IOException {
        //创建字节输出流对象
        //public FileOutputStream(String name)
        FileOutputStream fos = new FileOutputStream("fos.txt");

        //将数据写入到文件输出流中
        //write(byte[] b)
        //先把字符串转为字节数组,因为字节输出流只能写入字节数组或者单个字节
        fos.write("hello,io".getBytes());

        //释放资源
        //关闭此文件输出流并释放与此流有关的所有系统资源
        fos.close();
    }
}

在这里插入图片描述
分析:

  • 在创建字节文件输出流时,文件可以不存在,如果文件不存在,就会在项目的根目录下自动创建一个文件
    在这里插入图片描述
  • 需要注意的是,对于字节文件输出流,他的write()方法参数里面的传入参数的都是字节数据,需要将字符数据转成字节数据才能写入到输出流中。
  • 使用完流以后,一定要关闭流,释放资源

例2:在例1的基础上,仍然向fos.txt文件中写入数据

public class FileOutputStreamDemo1
{
    public static void main(String[] args) throws IOException
    {
        //创建字节输出流对象
        FileOutputStream fos = new FileOutputStream("fos.txt");

        //write(int b)一次写入一个字节数据
        fos.write(97);

        //write(byte[] b)一次写入一个字节数组
        byte[] bys = {97,98,99,100,101};
        fos.write(bys);

        //write(byte[] b,int off,int len)一次写入一个字节数组,并且指定字节数组的长度
        fos.write(bys, 1, 3);

        //释放资源
        fos.close();
    }
}

在这里插入图片描述
分析:可以看到再次向文件中写入数据时,就会将文件中之前的数据覆盖掉

例3:在例1的基础上向fos.txt文件中追加写入数据
这个时候,使用构造方法public FileOutputStream(String name,boolean append)

public class FileOutputStreamDemo2
{
    public static void main(String[] args) throws IOException
    {
        //创建字节输出流对象
        FileOutputStream fos = new FileOutputStream("fos.txt");

        //write(byte[] b)一次写入一个字节数组
        byte[] bys = {97,98,99,100,101};
        fos.write(bys,1,3);

        //释放资源
        fos.close();
    }
}

在这里插入图片描述

3. 字符文件输出流(FileWriter)

  1. 什么是字符文件输出流??
    简单讲,字符文件输出流就是将字符数据写入到输出流中
    在这里插入图片描述
    它是用来写入字符文件的便捷类,使用默认字符编码集进行编码,默认的缓冲区大小,要自己指定这些值,可以先在 FileOutputStream 上构造一个 OutputStreamWriter。(这个原因会在下个知识点中讲解)

  2. 字符文件输出流的构造方法:
    (1)根据给定的 File 对象构造一个 FileWriter 对象:
      public FileWriter(File file)
    (2)根据给定的 File 对象构造一个 FileWriter 对象。如果第二个参数为 true,则将字节写入文件末尾处,而不是写入文件开始处。
      public FileWriter(File file,boolean append)
    (3)根据给定的文件名构造一个 FileWriter 对象。
      public FileWriter(String fileName)
    (4)根据给定的文件名构造一个 FileWriter 对象。如果第二个参数为 true,则将字节写入文件末尾处,而不是写入文件开始处。
      public FileWriter(String fileName,boolean append)
      
    注意:如果指定文件存在,但它是一个目录,而不是一个常规文件;或者该文件不存在,但无法创建它;抑或因为其他某些原因而无法打开它,会抛出IOException。并且使用构造方法创建的是流对象,可以向这个流中写入数据。没有流对象是没有流的。

  3. 字符文件输出流的常用方法:
    (1)写入单个字符:
      public void write(int c)
    (2)写入字符数组的某一部分:
      public void write(char[] cbuf,int off,int len)
    (3)写入字符串的某一部分:
      public void write(String str, int off,int len)
    (4)刷新该流的缓冲:
      public abstract void flush()
    (5)关闭此流,但要先刷新它:
      public abstract void close()
      
    注意:对于字符输出流,因为电脑中文件中的数据都是以字节的形式保存的,而字符占用两个字节,所以进不到文件中而是在缓冲区中,需要刷新一下,也就是说,每写入一次数据都要刷新一下才能把数据从缓冲区刷新到文件中,但是如果觉得麻烦,可以在最后使用close()方法,因为close()方法调用时默认先刷新。

例1:向文件demo.txt中写入数据

public class FileWriterDemo
{
    public static void main(String[] args) throws IOException {
        /*
         *	如果文件不存在,则会自动创建
         *	如果文件存在,则会被覆盖
         */
        //创建一个可以往文件中写入字符数据的字符输出流对象
        FileWriter fw = new FileWriter("demo.txt");

        //将字符数据写入到临时存储缓冲区中
        fw.write("henghengaijianghui");

        //进行刷新,将数据直接写入到文件中
        fw.flush();

        //关闭流,关闭资源
        fw.close();
    }
}

在这里插入图片描述
分析:

  1. 首先需要创建一个流对象,用来向这个流中写入数据
  2. 对于字符数据不会直接写入文件中,而是先保存在缓冲区中,再刷新到文件中。
  3. 对于字符文件输出流,可以直接向里面写入字符数据,比较方便。

例2:使用带追加写入的构造方法创建流对象

public class FileWriterDemo1
{
    private static final String LINE_SEPARATOR = System.getProperty("line.separator");
    public static void main(String[] args) throws IOException
    {
        //使用构造方法实现对文件的追加续写
        FileWriter fw = new FileWriter("demo.txt",true);
        fw.write("henghengai"+LINE_SEPARATOR+"jianghui");
        fw.close();
    }
}

在这里插入图片描述

4. 转换流(OutputStreamWriter)

  1. 什么是转换流??
    OutputStreamWriter是字符流通向字节流的桥梁:可以使用指定的编码集将要写入的字符编码为字节,他所指定的编码集可以由名称指定或者显示的指定,否则将使用平台默认的编码集。

  2. 每次调用 write() 方法都会导致在给定字符(或字符集)上调用编码转换器。在写入底层输出流之前,得到的这些字节将在缓冲区中累积。
    为了获得最高效率,可考虑将 OutputStreamWriter 包装到 BufferedWriter 中,以避免频繁调用转换器。

  3. 通过FileWriter进一步理解转换流的作用:
    在这里插入图片描述
    FileWriter继承了OutputStreamWriter:
    转换流OutputStreamWriter将字符数据转换为字节数据,然后将其写入到文件中,而这个转换流就可以指定字符编码方式,
    FileWriter相当于使用了默认的字符编码方式即UTF-8,将字符数据转换为字节数据写入文件中。 如果,不想使用UTF-8,就需要使用转换流,将要写入的字符数据转换为字节数据,写入到文件中。

  4. OutputStreamWriter的构造方法:
    (1)创建使用指定字符集的OutputStreamWriter:
      public OutputStreamWriter(OutputStream out,String charsetName)
    (2)创建使用默认字符编码的 OutputStreamWriter。
      public OutputStreamWriter(OutputStream out)

  5. OutputStreamWriter的常用方法:
    (1)写入字符数组的某一部分:
      public void write(char[] cbuf,int off,int len)
    (2)写入字符串的某一部分:
      public void write(String str,int off, int len)
    (3)写入单个字符:
      public void write(int c)

例1:向文件中写入中文字符:指定字符编码方式为GBK

public class OutputStreamWriterDemo
{
    public static void main(String[] args) throws IOException
    {
        //指定使用GBK
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("osw.txt"),"GBK");
        osw.write("中国");
        osw.close();
    }
}

在这里插入图片描述
在这里插入图片描述
分析:

  • 要写入的数据为字符数据,“中国”
  • 如果我们想使用默认的编码方式将“中国”这两个字写入文件中,可以使用FileWriter
  • 如果我们不想使用默认的编码方式,可以使用转换流指定编码方式,将“中国”这两个字写入到文件中

例2 :向文件中写入中文字符:指定字符编码方式为UTF-8

public class OutputStreamWriterDemo1
{
    public static void main(String[] args) throws IOException
    {
        //指定使用GBK
        OutputStreamWriter osw = 
        	new OutputStreamWriter(new FileOutputStream("osw.txt"),"UTF-8");
        osw.write("中国");
        osw.close();
    }
}

在这里插入图片描述
在这里插入图片描述

5. 字节输出缓冲流(BufferedOutputStream)

  1. 什么是缓冲流?
    实现缓冲的输出流。通过设置这种输出流,应用程序就可以将各个字节写入底层输出流中,而不必针对每次字节写入调用底层系统,可以提高效率。
  2. 构造方法:
    创建一个新的缓冲输出流,以将数据写入指定的底层输出流:
     public BufferedOutputStream(OutputStream out)
  3. 方法:
    (1)将指定的字节写入此缓冲的输出流:
      public void write(int b)
    (2)将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此缓冲的输出流:
      public void write(byte[] b, int off, int len)
    (3)刷新此缓冲的输出流。这迫使所有缓冲的输出字节被写出到底层输出流中:
      public void flush()
      
    注意:一般来说,将给定数组的字节存入此流的缓冲区中,根据需要将该缓冲区刷新,并转到底层输出流。

例1:利用缓冲流将字节数据写入到文件中

public class BufferedOutputStreamDemo
{
    public static void main(String[] args) throws IOException
    {
        BufferedOutputStream bos =
                new BufferedOutputStream(new FileOutputStream("bos.txt"));
        //写数据
        bos.write("hello".getBytes());
        //释放资源
        bos.close();
    }
}

6. 字符输出缓冲流(BufferedWriter)

  1. 作用:
    将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。可以指定缓冲区的大小,或者接受默认的大小。在大多数情况下,默认值就足够大了。
  2. 构造方法:
    创建一个使用默认大小输出缓冲区的缓冲字符输出流:
     public BufferedWriter(Writer out)
  3. 方法:
    (1)写入单个字符。
      public void write(int c)
    (2)写入字符数组的某一部分。
      public void write(char[] cbuf, int off, int len)
    (3)写入字符串的某一部分。
      public void write(String s, int off,int len)
    (4)刷新该流的缓冲。
      public void flush()
    (5)写入一个行分隔符。行分隔符字符串由系统属性 line.separator 定义,并且不一定是单个新行 (’\n’) 符。
      public void newLine()

例1:使用字符输出缓冲流向文件中写入数据

public class BufferedWriterDemo
{
    public static void main(String[] args) throws IOException
    {
        //创建一个文件输出流
        FileWriter fw = new FileWriter("buffered.txt");
        
        //为了提高写入的效率,使用字符流缓冲区
        BufferedWriter bufw = new BufferedWriter(fw);
        
        //使用缓冲区的写入方法,将数据先写入到缓冲区中
        bufw.write("abdskkdk");
        
        //使用缓冲区的刷新方法将数据刷新到目的地中
        bufw.flush();
        
        //关闭缓冲区
        bufw.close();
    }
}

例2:使用平台默认的换行方法对输入的数据进行换行

public class BufferedWriterDemo2
{
    public static void main(String[] args) throws IOException
    {
        FileWriter fw = new FileWriter("buffered.txt");
        BufferedWriter bufw = new BufferedWriter(fw);

        for(int x=1;x<=4;x++)
        {
            bufw.write("abcdef"+x);
            //字符输出流加入缓冲区之后,有平台自身的换行方法
            bufw.newLine();
            bufw.flush();
        }
        //关闭缓冲区
        bufw.close();
    }
}

在这里插入图片描述

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!